gitwise-cli 0.30.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.30.0 → gitwise_cli-0.32.0}/CHANGELOG.md +16 -0
  2. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/PKG-INFO +1 -1
  3. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/__init__.py +1 -1
  4. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_cli_dispatch.py +121 -78
  5. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_cli_parser.py +18 -3
  6. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_cli_setup_agents.py +4 -0
  7. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_i18n_data.json +36 -0
  8. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/audit.py +9 -8
  9. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/branches.py +7 -7
  10. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/clean.py +15 -11
  11. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/commit.py +79 -9
  12. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/conflicts.py +12 -10
  13. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/context.py +25 -15
  14. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/diff.py +90 -26
  15. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/doctor.py +12 -10
  16. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/health.py +7 -7
  17. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/log.py +93 -79
  18. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/merge.py +14 -13
  19. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/optimize.py +14 -11
  20. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/pick.py +10 -10
  21. {gitwise_cli-0.30.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.30.0 → gitwise_cli-0.32.0}/gitwise/setup.py +17 -13
  24. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/format.py +8 -0
  25. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/show.py +7 -7
  26. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/snapshot.py +6 -6
  27. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/stash.py +15 -13
  28. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/status.py +83 -35
  29. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/suggest.py +17 -8
  30. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/summarize.py +9 -9
  31. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/sync.py +14 -9
  32. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/tag.py +45 -18
  33. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/undo.py +7 -6
  34. {gitwise_cli-0.30.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/secret_scan.py +201 -0
  37. gitwise_cli-0.32.0/gitwise/utils/types.py +80 -0
  38. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/worktree.py +15 -8
  39. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/pyproject.toml +1 -1
  40. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/commit.json +5 -0
  41. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/diff.json +5 -0
  42. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/schema.json +5 -0
  43. gitwise_cli-0.32.0/share/schemas/v1/output/diff.json +79 -0
  44. gitwise_cli-0.32.0/share/schemas/v1/output/log.json +57 -0
  45. gitwise_cli-0.32.0/share/schemas/v1/output/setup-agents.json +49 -0
  46. gitwise_cli-0.32.0/share/schemas/v1/output/status.json +103 -0
  47. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_audit.py +15 -14
  48. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_branches.py +2 -2
  49. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_clean.py +9 -9
  50. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_commit.py +58 -0
  51. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_conflicts.py +3 -3
  52. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_context.py +7 -6
  53. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_diff.py +45 -9
  54. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_doctor.py +12 -8
  55. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_edge_cases.py +10 -7
  56. gitwise_cli-0.32.0/tests/test_envelope_contract.py +69 -0
  57. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_git.py +6 -6
  58. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_health.py +5 -5
  59. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_i18n.py +1 -1
  60. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_in_progress.py +4 -4
  61. gitwise_cli-0.32.0/tests/test_json_envelope_utils.py +76 -0
  62. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_log.py +47 -9
  63. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_main.py +42 -22
  64. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_merge.py +4 -4
  65. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_optimize.py +10 -8
  66. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_output.py +3 -3
  67. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_pick.py +4 -4
  68. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_pr.py +7 -7
  69. gitwise_cli-0.32.0/tests/test_schema_catalog.py +99 -0
  70. gitwise_cli-0.32.0/tests/test_secret_scan.py +177 -0
  71. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_setup.py +13 -11
  72. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_stash.py +3 -3
  73. gitwise_cli-0.32.0/tests/test_status.py +116 -0
  74. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_suggest.py +4 -4
  75. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_summarize.py +11 -9
  76. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_sync.py +2 -2
  77. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_tag.py +12 -12
  78. gitwise_cli-0.32.0/tests/test_types.py +59 -0
  79. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_worktree.py +3 -3
  80. gitwise_cli-0.30.0/gitwise/schema.py +0 -54
  81. gitwise_cli-0.30.0/gitwise/utils/json_envelope.py +0 -75
  82. gitwise_cli-0.30.0/tests/test_json_envelope_utils.py +0 -36
  83. gitwise_cli-0.30.0/tests/test_schema_catalog.py +0 -45
  84. gitwise_cli-0.30.0/tests/test_status.py +0 -52
  85. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/.gitignore +0 -0
  86. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/LICENSE +0 -0
  87. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/README.md +0 -0
  88. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/bin/gitwise +0 -0
  89. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/__main__.py +0 -0
  90. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_cli_completions.py +0 -0
  91. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_cli_introspection.py +0 -0
  92. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_paths.py +0 -0
  93. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/_runtime_config.py +0 -0
  94. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/design.py +0 -0
  95. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/git.py +0 -0
  96. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/i18n.py +0 -0
  97. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/output.py +0 -0
  98. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/py.typed +0 -0
  99. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/__init__.py +0 -0
  100. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/__init__.py +0 -0
  101. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/aider.py +0 -0
  102. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/base.py +0 -0
  103. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/codex.py +0 -0
  104. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/continue_adapter.py +0 -0
  105. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/cursor.py +0 -0
  106. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/opencode.py +0 -0
  107. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/adapters/pi.py +0 -0
  108. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/exec.py +0 -0
  109. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan.py +0 -0
  110. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan_gitfiles.py +0 -0
  111. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/plan_skills.py +0 -0
  112. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/__init__.py +0 -0
  113. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/aider.py +0 -0
  114. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/base.py +0 -0
  115. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/claude.py +0 -0
  116. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/codex.py +0 -0
  117. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/continue_adapter.py +0 -0
  118. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/cursor.py +0 -0
  119. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/opencode.py +0 -0
  120. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/providers/pi.py +0 -0
  121. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/state.py +0 -0
  122. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/setup_agents/types.py +0 -0
  123. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/utils/__init__.py +0 -0
  124. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/utils/git_output.py +0 -0
  125. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/utils/in_progress.py +0 -0
  126. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/gitwise/utils/parsing.py +0 -0
  127. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/install.sh +0 -0
  128. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/agents/skills/git-audit/SKILL.md +0 -0
  129. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/agents/skills/git-clean/SKILL.md +0 -0
  130. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/agents/skills/git-optimize/SKILL.md +0 -0
  131. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/aider/CONVENTIONS.md.template +0 -0
  132. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/aider/aider.conf.yml.template +0 -0
  133. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/CLAUDE.md.template +0 -0
  134. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/rules/gitwise.md +0 -0
  135. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/settings.json.template +0 -0
  136. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/skills/git-audit/SKILL.md +0 -0
  137. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/skills/git-clean/SKILL.md +0 -0
  138. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/claude/skills/git-optimize/SKILL.md +0 -0
  139. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/codex/agents/gitwise.toml.template +0 -0
  140. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/continue/rules/gitwise.md.template +0 -0
  141. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/cursor/rules/gitwise.mdc.template +0 -0
  142. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/git-config-modern.txt +0 -0
  143. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/hooks/commit-msg +0 -0
  144. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/hooks/pre-commit +0 -0
  145. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/opencode/agents/gitwise.md.template +0 -0
  146. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/pi/skills/gitwise.md.template +0 -0
  147. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/audit.json +0 -0
  148. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/branches.json +0 -0
  149. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/clean.json +0 -0
  150. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/commands.json +0 -0
  151. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/completions.json +0 -0
  152. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/conflicts.json +0 -0
  153. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/context.json +0 -0
  154. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/doctor.json +0 -0
  155. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/health.json +0 -0
  156. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/log.json +0 -0
  157. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/merge.json +0 -0
  158. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/optimize.json +0 -0
  159. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/pick.json +0 -0
  160. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/pr.json +0 -0
  161. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/setup-agents.json +0 -0
  162. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/setup.json +0 -0
  163. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/show.json +0 -0
  164. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/snapshot.json +0 -0
  165. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/stash.json +0 -0
  166. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/status.json +0 -0
  167. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/suggest.json +0 -0
  168. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/summarize.json +0 -0
  169. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/sync.json +0 -0
  170. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/tag.json +0 -0
  171. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/undo.json +0 -0
  172. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/update.json +0 -0
  173. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/share/schemas/v1/input/worktree.json +0 -0
  174. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/__init__.py +0 -0
  175. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/conftest.py +0 -0
  176. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_adapters.py +0 -0
  177. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_design.py +0 -0
  178. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_git_output_utils.py +0 -0
  179. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_md_links_script.py +0 -0
  180. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_parsing_utils.py +0 -0
  181. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_roadmap_baseline_script.py +0 -0
  182. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_sa_plan.py +0 -0
  183. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_sa_unit.py +0 -0
  184. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_setup_agents.py +0 -0
  185. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_show.py +0 -0
  186. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_snapshot.py +0 -0
  187. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_sync_changelog_es_script.py +0 -0
  188. {gitwise_cli-0.30.0 → gitwise_cli-0.32.0}/tests/test_undo.py +0 -0
@@ -3,6 +3,22 @@
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
+
16
+ ## v0.31.0 (2026-06-19)
17
+
18
+ ### Feat
19
+
20
+ - **secret-scan**: commit-time guard and diff --scan-secrets (Sprint 2 D3) (#68)
21
+
6
22
  ## v0.30.0 (2026-06-19)
7
23
 
8
24
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitwise-cli
3
- Version: 0.30.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.30.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
@@ -193,13 +204,14 @@ def _run_diff(args: argparse.Namespace) -> int:
193
204
  name_only=args.name_only,
194
205
  full=args.full,
195
206
  summary=args.summary,
207
+ scan_secrets=args.scan_secrets,
196
208
  as_json=args.json,
197
209
  )
198
210
 
199
211
 
200
212
  def _run_log(args: argparse.Namespace) -> int:
201
213
  """Dispatch to ``log`` subcommand."""
202
- from .log import run_log
214
+ from gitwise.log import run_log
203
215
 
204
216
  return run_log(
205
217
  as_json=args.json,
@@ -216,14 +228,14 @@ def _run_log(args: argparse.Namespace) -> int:
216
228
 
217
229
  def _run_show(args: argparse.Namespace) -> int:
218
230
  """Dispatch to ``show`` subcommand."""
219
- from .show import run_show
231
+ from gitwise.show import run_show
220
232
 
221
233
  return run_show(ref=args.ref, stat=args.stat, as_json=args.json)
222
234
 
223
235
 
224
236
  def _run_commit(args: argparse.Namespace) -> int:
225
237
  """Dispatch to ``commit`` subcommand."""
226
- from .commit import run_commit
238
+ from gitwise.commit import run_commit
227
239
 
228
240
  return run_commit(
229
241
  message=args.message,
@@ -232,20 +244,21 @@ def _run_commit(args: argparse.Namespace) -> int:
232
244
  breaking=args.breaking,
233
245
  amend=args.amend,
234
246
  dry_run=args.dry_run,
247
+ allow_secret=args.allow_secret,
235
248
  as_json=args.json,
236
249
  )
237
250
 
238
251
 
239
252
  def _run_branches(args: argparse.Namespace) -> int:
240
253
  """Dispatch to ``branches`` subcommand."""
241
- from .branches import run_branches
254
+ from gitwise.branches import run_branches
242
255
 
243
256
  return run_branches(stale=args.stale, remote=args.remote, sort=args.sort, as_json=args.json)
244
257
 
245
258
 
246
259
  def _run_sync(args: argparse.Namespace) -> int:
247
260
  """Dispatch to ``sync`` subcommand."""
248
- from .sync import run_sync
261
+ from gitwise.sync import run_sync
249
262
 
250
263
  return run_sync(
251
264
  pull=args.pull,
@@ -258,14 +271,14 @@ def _run_sync(args: argparse.Namespace) -> int:
258
271
 
259
272
  def _run_pr(args: argparse.Namespace) -> int:
260
273
  """Dispatch to ``pr`` subcommand."""
261
- from .pr import run_pr
274
+ from gitwise.pr import run_pr
262
275
 
263
276
  return run_pr(action=args.action, selector=args.selector, as_json=args.json)
264
277
 
265
278
 
266
279
  def _run_undo(args: argparse.Namespace) -> int:
267
280
  """Dispatch to ``undo`` subcommand."""
268
- from .undo import run_undo
281
+ from gitwise.undo import run_undo
269
282
 
270
283
  return run_undo(
271
284
  ref=args.ref,
@@ -279,21 +292,21 @@ def _run_undo(args: argparse.Namespace) -> int:
279
292
 
280
293
  def _run_context(args: argparse.Namespace) -> int:
281
294
  """Dispatch to ``context`` subcommand."""
282
- from .context import run_context
295
+ from gitwise.context import run_context
283
296
 
284
297
  return run_context(as_json=args.json)
285
298
 
286
299
 
287
300
  def _run_health(args: argparse.Namespace) -> int:
288
301
  """Dispatch to ``health`` subcommand."""
289
- from .health import run_health
302
+ from gitwise.health import run_health
290
303
 
291
304
  return run_health(as_json=args.json)
292
305
 
293
306
 
294
307
  def _run_stash(args: argparse.Namespace) -> int:
295
308
  """Dispatch to ``stash`` subcommand."""
296
- from .stash import run_stash
309
+ from gitwise.stash import run_stash
297
310
 
298
311
  return run_stash(
299
312
  action=args.action,
@@ -307,7 +320,7 @@ def _run_stash(args: argparse.Namespace) -> int:
307
320
 
308
321
  def _run_tag(args: argparse.Namespace) -> int:
309
322
  """Dispatch to ``tag`` subcommand."""
310
- from .tag import run_tag
323
+ from gitwise.tag import run_tag
311
324
 
312
325
  return run_tag(
313
326
  action=args.action,
@@ -322,7 +335,7 @@ def _run_tag(args: argparse.Namespace) -> int:
322
335
 
323
336
  def _run_merge(args: argparse.Namespace) -> int:
324
337
  """Dispatch to ``merge`` subcommand."""
325
- from .merge import run_merge
338
+ from gitwise.merge import run_merge
326
339
 
327
340
  return run_merge(
328
341
  args.branch,
@@ -338,21 +351,21 @@ def _run_merge(args: argparse.Namespace) -> int:
338
351
 
339
352
  def _run_conflicts(args: argparse.Namespace) -> int:
340
353
  """Dispatch to ``conflicts`` subcommand."""
341
- from .conflicts import run_conflicts
354
+ from gitwise.conflicts import run_conflicts
342
355
 
343
356
  return run_conflicts(ours=args.ours, theirs=args.theirs, as_json=args.json)
344
357
 
345
358
 
346
359
  def _run_suggest(args: argparse.Namespace) -> int:
347
360
  """Dispatch to ``suggest`` subcommand."""
348
- from .suggest import run_suggest
361
+ from gitwise.suggest import run_suggest
349
362
 
350
363
  return run_suggest(as_json=args.json)
351
364
 
352
365
 
353
366
  def _run_pick(args: argparse.Namespace) -> int:
354
367
  """Dispatch to ``pick`` / ``cherry-pick`` subcommand."""
355
- from .pick import run_pick
368
+ from gitwise.pick import run_pick
356
369
 
357
370
  return run_pick(
358
371
  args.refs,
@@ -366,7 +379,7 @@ def _run_pick(args: argparse.Namespace) -> int:
366
379
 
367
380
  def _run_status(args: argparse.Namespace) -> int:
368
381
  """Dispatch to ``status`` subcommand."""
369
- from .status import run_status
382
+ from gitwise.status import run_status
370
383
 
371
384
  return run_status(as_json=args.json)
372
385
 
@@ -382,46 +395,49 @@ def _run_completions(args: argparse.Namespace) -> int:
382
395
  try:
383
396
  script = build_completions_script(shell=shell, prog=prog)
384
397
  except ModuleNotFoundError:
385
- from .output import error as _error
398
+ from gitwise.output import error as _error
386
399
 
387
400
  hint = t("missing_dependency_hint")
388
401
  message = t("missing_dependency_completions_shtab")
389
402
  if args.json:
390
- 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
+ )
391
406
  else:
392
407
  _error(message, hint=hint)
393
408
  return 1
394
409
  except RuntimeError as e:
395
410
  message = str(e)
396
411
  if args.json:
397
- print_json(error_envelope(error=message, code="runtime_error"))
412
+ print_json(error_envelope("completions", error=message, code="runtime_error"))
398
413
  else:
399
- from .output import error as _error
414
+ from gitwise.output import error as _error
400
415
 
401
416
  _error(message)
402
417
  return 1
403
418
  except ValueError:
404
419
  message = t("completions_unsupported_shell", shell=shell)
405
420
  if args.json:
406
- print_json(error_envelope(error=message, code="unsupported_shell"))
421
+ print_json(error_envelope("completions", error=message, code="unsupported_shell"))
407
422
  else:
408
- from .output import error as _error
423
+ from gitwise.output import error as _error
409
424
 
410
425
  _error(message)
411
426
  return 1
412
427
 
413
428
  if args.json:
414
429
  print_json(
415
- {
416
- "v": 2,
417
- "ok": True,
418
- "kind": "completions",
419
- "schema": "gitwise/completions/v1",
420
- "version": __version__,
421
- "shell": shell,
422
- "prog": prog,
423
- "script": script,
424
- }
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
+ )
425
441
  )
426
442
  return 0
427
443
 
@@ -433,14 +449,15 @@ def _run_commands(args: argparse.Namespace) -> int:
433
449
  """List all registered subcommands with aliases."""
434
450
  parser = build_parser()
435
451
  commands = commands_metadata(parser)
436
- payload = {
437
- "v": 2,
438
- "ok": True,
439
- "kind": "commands",
440
- "schema": "gitwise/commands/v1",
441
- "version": __version__,
442
- "commands": commands,
443
- }
452
+ payload = ok_envelope(
453
+ "commands",
454
+ data={
455
+ "kind": "commands",
456
+ "schema": "gitwise/commands/v1",
457
+ "version": __version__,
458
+ "commands": commands,
459
+ },
460
+ )
444
461
 
445
462
  if args.json:
446
463
  print_json(payload)
@@ -463,7 +480,7 @@ def _run_schema(args: argparse.Namespace) -> int:
463
480
 
464
481
  Returns 1 when the command is unknown or its schema file is missing.
465
482
  """
466
- from .schema import load_command_input_schema
483
+ from gitwise.schema import load_command_input_schema
467
484
 
468
485
  parser = build_parser()
469
486
  command_parser = resolve_command_parser(parser=parser, name=args.name)
@@ -473,6 +490,7 @@ def _run_schema(args: argparse.Namespace) -> int:
473
490
  if args.json:
474
491
  print_json(
475
492
  error_envelope(
493
+ "schema",
476
494
  error=message,
477
495
  code="unknown_command",
478
496
  hint=hint,
@@ -481,12 +499,35 @@ def _run_schema(args: argparse.Namespace) -> int:
481
499
  )
482
500
  )
483
501
  else:
484
- from .output import error as _error
502
+ from gitwise.output import error as _error
485
503
 
486
504
  _error(message, hint=hint)
487
505
  return 1
488
506
 
489
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
+
490
531
  schema = load_command_input_schema(command=name, version=args.version)
491
532
  if schema is None:
492
533
  message = t("schema_file_missing", command=name, version=args.version)
@@ -494,6 +535,7 @@ def _run_schema(args: argparse.Namespace) -> int:
494
535
  if args.json:
495
536
  print_json(
496
537
  error_envelope(
538
+ "schema",
497
539
  error=message,
498
540
  code="schema_not_found",
499
541
  hint=hint,
@@ -502,22 +544,23 @@ def _run_schema(args: argparse.Namespace) -> int:
502
544
  )
503
545
  )
504
546
  else:
505
- from .output import error as _error
547
+ from gitwise.output import error as _error
506
548
 
507
549
  _error(message, hint=hint)
508
550
  return 1
509
551
 
510
- payload = {
511
- "v": 2,
512
- "ok": True,
513
- "kind": "schema",
514
- "schema": "gitwise/schema/v1",
515
- "version": __version__,
516
- "schema_version": args.version,
517
- "command": name,
518
- "schema_kind": "cli_input",
519
- "json_schema": schema,
520
- }
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
+ )
521
564
 
522
565
  print_json(payload)
523
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:
@@ -184,6 +184,11 @@ def build_parser() -> argparse.ArgumentParser:
184
184
  help="compact summary: additions/deletions per file, no patch",
185
185
  )
186
186
  p.add_argument("--stat", action="store_true", help="show diffstat (default behavior)")
187
+ p.add_argument(
188
+ "--scan-secrets",
189
+ action="store_true",
190
+ help="scan the diff for leaked credentials (advisory, opt-in)",
191
+ )
187
192
  p.add_argument(
188
193
  "refspec",
189
194
  nargs="?",
@@ -218,6 +223,11 @@ def build_parser() -> argparse.ArgumentParser:
218
223
  p.add_argument("--breaking", action="store_true", help="breaking change (!)")
219
224
  p.add_argument("--amend", action="store_true", help="amend last commit")
220
225
  p.add_argument("--dry-run", action="store_true", help="show without committing")
226
+ p.add_argument(
227
+ "--allow-secret",
228
+ action="store_true",
229
+ help="proceed past a high-severity secret finding (with confirmation)",
230
+ )
221
231
 
222
232
  p = sub.add_parser("branches", help="branch intelligence dashboard", parents=[parent])
223
233
  p.add_argument("--stale", action="store_true", help="show stale [gone] branches only")
@@ -351,6 +361,11 @@ def build_parser() -> argparse.ArgumentParser:
351
361
  default="v1",
352
362
  help="schema catalog version (default: v1)",
353
363
  )
364
+ p.add_argument(
365
+ "--output",
366
+ action="store_true",
367
+ help="show the command's --json output schema (default: input schema)",
368
+ )
354
369
 
355
370
  p = sub.add_parser(
356
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"),
@@ -463,6 +463,38 @@
463
463
  "es": "demasiados argumentos posicionales antes de '--' ({count}); gitwise diff acepta un unico refspec (usa a..b para un rango)",
464
464
  "en": "too many positional arguments before '--' ({count}); gitwise diff accepts a single refspec (use a..b for a range)"
465
465
  },
466
+ "secret_scan_clean": {
467
+ "es": "no se detectaron secretos en el diff",
468
+ "en": "no secrets detected in the diff"
469
+ },
470
+ "secret_scan_found": {
471
+ "es": "{rule} en {path}:{line} ({preview})",
472
+ "en": "{rule} at {path}:{line} ({preview})"
473
+ },
474
+ "secret_scan_found_header": {
475
+ "es": "Secretos detectados -- {count} hallazgo(s):",
476
+ "en": "Secrets detected -- {count} finding(s):"
477
+ },
478
+ "secret_scan_blocked_high": {
479
+ "es": "commit bloqueado: {count} secreto(s) de alta severidad en el área de staging",
480
+ "en": "commit blocked: {count} high-severity secret(s) in the staging area"
481
+ },
482
+ "secret_scan_blocked_hint": {
483
+ "es": "revoque o rote el secreto, remuévalo del stage, o use --allow-secret (con confirmación) para commitear de todos modos",
484
+ "en": "revoke/rotate the secret, unstage it, or use --allow-secret (with confirmation) to commit anyway"
485
+ },
486
+ "secret_scan_allow_confirm": {
487
+ "es": "Se detectaron {count} secreto(s) de alta severidad. ¿Commitear de todos modos?",
488
+ "en": "{count} high-severity secret(s) detected. Commit anyway?"
489
+ },
490
+ "secret_scan_medium_warning": {
491
+ "es": "advertencia: {rule} en {path}:{line} ({preview})",
492
+ "en": "warning: {rule} at {path}:{line} ({preview})"
493
+ },
494
+ "secret_scan_unavailable": {
495
+ "es": "no se pudo escanear el área de staging (fail-closed): {error}",
496
+ "en": "could not scan the staging area (fail-closed): {error}"
497
+ },
466
498
  "directory_exists": {
467
499
  "es": "el directorio ya existe: {path}",
468
500
  "en": "directory already exists: {path}"
@@ -1551,6 +1583,10 @@
1551
1583
  "es": "{count} archivo(s) en área de preparación",
1552
1584
  "en": "{count} file(s) staged"
1553
1585
  },
1586
+ "status_conflicted_label": {
1587
+ "es": "en conflicto",
1588
+ "en": "conflicted"
1589
+ },
1554
1590
  "status_staged_label": {
1555
1591
  "es": "preparados",
1556
1592
  "en": "staged"