git-cai-cli 0.12.0__tar.gz → 0.12.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 (87) hide show
  1. {git_cai_cli-0.12.0/src/git_cai_cli.egg-info → git_cai_cli-0.12.2}/PKG-INFO +1 -1
  2. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/docs/git-cai.txt +7 -6
  3. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/docs/man/git-cai.1 +9 -8
  4. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/_version.py +3 -3
  5. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/cli/modes.py +2 -2
  6. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/llm.py +12 -2
  7. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/options.py +2 -0
  8. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/squash.py +5 -1
  9. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/main.py +1 -0
  10. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2/src/git_cai_cli.egg-info}/PKG-INFO +1 -1
  11. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_llm.py +42 -0
  12. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_modes.py +13 -20
  13. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_squash.py +28 -0
  14. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.caiignore +0 -0
  15. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.gitattributes +0 -0
  16. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/cd/.SRCINFO +0 -0
  17. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/cd/PKGBUILD +0 -0
  18. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/ci/_version.py +0 -0
  19. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/ci/cai_config.ci.yml +0 -0
  20. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/ci/tokens.ci.yml +0 -0
  21. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/workflows/python-tests.yml +0 -0
  22. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/workflows/release.yml +0 -0
  23. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.github/workflows/release_aur.yml +0 -0
  24. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.gitignore +0 -0
  25. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.bandit.yml +0 -0
  26. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.checkov.yml +0 -0
  27. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.flake8 +0 -0
  28. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.ls-lint.yml +0 -0
  29. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.markdown-link-check.json +0 -0
  30. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.markdownlint.json +0 -0
  31. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.proselintrc +0 -0
  32. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.pylintrc +0 -0
  33. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/.yamllint.yml +0 -0
  34. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/check_git_branch_name.sh +0 -0
  35. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/lychee.toml +0 -0
  36. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.linters/pyrightconfig.json +0 -0
  37. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.markdownlintignore +0 -0
  38. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.mega-linter.yml +0 -0
  39. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.semgrepignore +0 -0
  40. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/.trivyignore +0 -0
  41. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/CLAUDE.md +0 -0
  42. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/LICENSE +0 -0
  43. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/Makefile +0 -0
  44. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/README.md +0 -0
  45. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/cai_config.yml +0 -0
  46. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/pyproject.toml +0 -0
  47. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/setup.cfg +0 -0
  48. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/__init__.py +0 -0
  49. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/cli/__init__.py +0 -0
  50. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/cli/cli.py +0 -0
  51. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/cli/helptext.py +0 -0
  52. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/__init__.py +0 -0
  53. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/completion.py +0 -0
  54. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/config.py +0 -0
  55. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/editors.py +0 -0
  56. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/gitutils.py +0 -0
  57. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/languages.py +0 -0
  58. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/prompts_fallback.py +0 -0
  59. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/spinner.py +0 -0
  60. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli/core/validate.py +0 -0
  61. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli.egg-info/SOURCES.txt +0 -0
  62. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli.egg-info/dependency_links.txt +0 -0
  63. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli.egg-info/entry_points.txt +0 -0
  64. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli.egg-info/requires.txt +0 -0
  65. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/src/git_cai_cli.egg-info/top_level.txt +0 -0
  66. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/conftest.py +0 -0
  67. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_cli_integration.py +0 -0
  68. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_config_integration.py +0 -0
  69. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_gitutils_integration.py +0 -0
  70. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_modes_integration.py +0 -0
  71. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_options_integration.py +0 -0
  72. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/integration/test_squash_integration.py +0 -0
  73. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_amend.py +0 -0
  74. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_branch_context.py +0 -0
  75. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_cli.py +0 -0
  76. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_completion.py +0 -0
  77. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_config.py +0 -0
  78. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_conventional.py +0 -0
  79. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_gitutils.py +0 -0
  80. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_helptext.py +0 -0
  81. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_main.py +0 -0
  82. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_options.py +0 -0
  83. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_prompt_loading.py +0 -0
  84. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_set_config.py +0 -0
  85. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_spinner.py +0 -0
  86. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/tests/unit/test_validate.py +0 -0
  87. {git_cai_cli-0.12.0 → git_cai_cli-0.12.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-cai-cli
3
- Version: 0.12.0
3
+ Version: 0.12.2
4
4
  Summary: Use LLM to create git commit messages
5
5
  Author-email: Thorsten Foltz <thorsten.foltz@live.com>
6
6
  License-Expression: MIT
@@ -399,18 +399,19 @@ git cai -v
399
399
 
400
400
  -x, --context CONTEXT::
401
401
  Provide extra context for the LLM to consider when generating the commit
402
- message. The context string is appended to the diff before sending it to
403
- the provider. This is useful for including information that is not visible
404
- in the diff itself, such as a ticket number, the reason for a change, or
405
- a link to an issue.
402
+ message. The context string is appended to the diff (or commit history in squash
403
+ mode) before sending it to the provider. This is useful for including information
404
+ that is not visible in the diff itself, such as a ticket number, the reason for
405
+ a change, or a link to an issue.
406
406
  +
407
- Can be combined with any commit-generating mode (`COMMIT` or `AMEND`).
408
- Cannot be used with `--list`, `--update`, or `--squash`.
407
+ Can be combined with any commit-generating mode (`COMMIT`, `AMEND`, or `SQUASH`).
408
+ Cannot be used with `--list` or `--update`.
409
409
  +
410
410
  ----
411
411
  git cai -x "Fixes JIRA-1234"
412
412
  git cai -x "Performance optimisation for the search endpoint"
413
413
  git cai -A -x "Reword after code review feedback"
414
+ git cai --squash -x "Resolves JIRA-99"
414
415
  ----
415
416
 
416
417
  LIST TYPES
@@ -2,12 +2,12 @@
2
2
  .\" Title: git-cai
3
3
  .\" Author: Thorsten Foltz
4
4
  .\" Generator: Asciidoctor 2.0.26
5
- .\" Date: 2026-04-17
5
+ .\" Date: 2026-04-23
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "GIT\-CAI" "1" "2026-04-17" "\ \&" "\ \&"
10
+ .TH "GIT\-CAI" "1" "2026-04-23" "\ \&" "\ \&"
11
11
  .ie \n(.g .ds Aq \(aq
12
12
  .el .ds Aq '
13
13
  .ss \n[.ss] 0
@@ -668,13 +668,13 @@ git cai \-v
668
668
  \-x, \-\-context CONTEXT
669
669
  .RS 4
670
670
  Provide extra context for the LLM to consider when generating the commit
671
- message. The context string is appended to the diff before sending it to
672
- the provider. This is useful for including information that is not visible
673
- in the diff itself, such as a ticket number, the reason for a change, or
674
- a link to an issue.
671
+ message. The context string is appended to the diff (or commit history in squash
672
+ mode) before sending it to the provider. This is useful for including information
673
+ that is not visible in the diff itself, such as a ticket number, the reason for
674
+ a change, or a link to an issue.
675
675
  .sp
676
- Can be combined with any commit\-generating mode (\f(CRCOMMIT\fP or \f(CRAMEND\fP).
677
- Cannot be used with \f(CR\-\-list\fP, \f(CR\-\-update\fP, or \f(CR\-\-squash\fP.
676
+ Can be combined with any commit\-generating mode (\f(CRCOMMIT\fP, \f(CRAMEND\fP, or \f(CRSQUASH\fP).
677
+ Cannot be used with \f(CR\-\-list\fP or \f(CR\-\-update\fP.
678
678
  .sp
679
679
  .if n .RS 4
680
680
  .nf
@@ -682,6 +682,7 @@ Cannot be used with \f(CR\-\-list\fP, \f(CR\-\-update\fP, or \f(CR\-\-squash\fP.
682
682
  git cai \-x "Fixes JIRA\-1234"
683
683
  git cai \-x "Performance optimisation for the search endpoint"
684
684
  git cai \-A \-x "Reword after code review feedback"
685
+ git cai \-\-squash \-x "Resolves JIRA\-99"
685
686
  .fam
686
687
  .fi
687
688
  .if n .RE
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.12.0'
22
- __version_tuple__ = version_tuple = (0, 12, 0)
21
+ __version__ = version = '0.12.2'
22
+ __version_tuple__ = version_tuple = (0, 12, 2)
23
23
 
24
- __commit_id__ = commit_id = 'g10d470d7a'
24
+ __commit_id__ = commit_id = 'gf511d4825'
@@ -87,9 +87,9 @@ def validate_options(
87
87
  )
88
88
  raise typer.Exit(code=1)
89
89
 
90
- if context and mode not in (Mode.COMMIT, Mode.AMEND):
90
+ if context and mode not in (Mode.COMMIT, Mode.AMEND, Mode.SQUASH):
91
91
  typer.echo(
92
- "Error: --context cannot be used with --list, --update, or --squash.",
92
+ "Error: --context cannot be used with --list or --update.",
93
93
  err=True,
94
94
  )
95
95
  raise typer.Exit(code=1)
@@ -168,13 +168,23 @@ class CommitMessageGenerator:
168
168
 
169
169
  return self._dispatch_generate(content=content, system_prompt=prompt)
170
170
 
171
- def summarize_commit_history(self, commit_messages: str) -> str:
171
+ def summarize_commit_history(
172
+ self, commit_messages: str, context: str | None = None
173
+ ) -> str:
172
174
  """
173
175
  Summarize multiple commit messages into one high-level commit message.
174
176
  """
175
177
  prompt = self._build_squash_prompt()
176
178
  log.debug("Squash system prompt preview: %r", prompt[:400])
177
- return self._dispatch_generate(content=commit_messages, system_prompt=prompt)
179
+
180
+ content = commit_messages
181
+ if context:
182
+ content = (
183
+ f"{commit_messages}\n\n"
184
+ f"--- Additional context from the author ---\n{context}"
185
+ )
186
+
187
+ return self._dispatch_generate(content=content, system_prompt=prompt)
178
188
 
179
189
  def _emoji_instruction(self) -> str:
180
190
  """
@@ -364,6 +364,7 @@ git cai -l style
364
364
  model_override: str | None = None,
365
365
  time_flag: bool = False,
366
366
  squash_arg: str | None = None,
367
+ context: str | None = None,
367
368
  ) -> None:
368
369
  """
369
370
  Squash commits on the current branch and summarize them.
@@ -373,6 +374,7 @@ git cai -l style
373
374
  model_override=model_override,
374
375
  time_flag=time_flag,
375
376
  squash_arg=squash_arg,
377
+ context=context,
376
378
  )
377
379
 
378
380
  def stage_tracked_files(self) -> None:
@@ -184,6 +184,7 @@ def squash_branch(
184
184
  model_override: str | None = None,
185
185
  time_flag: bool = False,
186
186
  squash_arg: str | None = None,
187
+ context: str | None = None,
187
188
  ) -> None:
188
189
  """
189
190
  Squash commits in the current branch into a single commit with an LLM-generated message.
@@ -192,6 +193,7 @@ def squash_branch(
192
193
  squash_arg: Optional. A number (squash last N commits) or a commit hash
193
194
  (squash up to and including that commit). If None, squash all
194
195
  commits since the branch diverged.
196
+ context: Optional. Extra context for the LLM (e.g. ticket number, reason for change).
195
197
  """
196
198
  repo_root = find_git_root()
197
199
  if not repo_root:
@@ -297,7 +299,9 @@ def squash_branch(
297
299
 
298
300
  try:
299
301
  with Spinner("Summarizing commit history"):
300
- summary_message = generator.summarize_commit_history(commit_log)
302
+ summary_message = generator.summarize_commit_history(
303
+ commit_log, context=context
304
+ )
301
305
  except ValueError as e:
302
306
  log.error("%s", e)
303
307
  sys.exit(1)
@@ -111,6 +111,7 @@ def run(
111
111
  model_override=model_override,
112
112
  time_flag=time_flag,
113
113
  squash_arg=list_arg,
114
+ context=context,
114
115
  )
115
116
  return
116
117
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-cai-cli
3
- Version: 0.12.0
3
+ Version: 0.12.2
4
4
  Summary: Use LLM to create git commit messages
5
5
  Author-email: Thorsten Foltz <thorsten.foltz@live.com>
6
6
  License-Expression: MIT
@@ -973,6 +973,48 @@ def test_generate_with_empty_context_passes_diff_only(generator):
973
973
  assert content == "diff output"
974
974
 
975
975
 
976
+ def test_summarize_appends_context_to_commit_messages(generator):
977
+ """summarize_commit_history() with context appends it after the messages."""
978
+ with patch.object(generator, "_dispatch_generate", return_value="summary") as mock:
979
+ generator.summarize_commit_history("commit messages", context="Closes #42")
980
+
981
+ call_args = mock.call_args
982
+ content = call_args[1]["content"] if "content" in call_args[1] else call_args[0][0]
983
+ assert "commit messages" in content
984
+ assert "--- Additional context from the author ---" in content
985
+ assert "Closes #42" in content
986
+
987
+
988
+ def test_summarize_without_context_passes_messages_only(generator):
989
+ """summarize_commit_history() without context passes only the messages."""
990
+ with patch.object(generator, "_dispatch_generate", return_value="summary") as mock:
991
+ generator.summarize_commit_history("commit messages")
992
+
993
+ call_args = mock.call_args
994
+ content = call_args[1]["content"] if "content" in call_args[1] else call_args[0][0]
995
+ assert content == "commit messages"
996
+
997
+
998
+ def test_summarize_with_none_context_passes_messages_only(generator):
999
+ """summarize_commit_history() with None context should pass only the messages."""
1000
+ with patch.object(generator, "_dispatch_generate", return_value="summary") as mock:
1001
+ generator.summarize_commit_history("commit messages", context=None)
1002
+
1003
+ call_args = mock.call_args
1004
+ content = call_args[1]["content"] if "content" in call_args[1] else call_args[0][0]
1005
+ assert content == "commit messages"
1006
+
1007
+
1008
+ def test_summarize_with_empty_context_passes_messages_only(generator):
1009
+ """summarize_commit_history() with empty string context should pass only the messages."""
1010
+ with patch.object(generator, "_dispatch_generate", return_value="summary") as mock:
1011
+ generator.summarize_commit_history("commit messages", context="")
1012
+
1013
+ call_args = mock.call_args
1014
+ content = call_args[1]["content"] if "content" in call_args[1] else call_args[0][0]
1015
+ assert content == "commit messages"
1016
+
1017
+
976
1018
  # ---- timeout resolution ----
977
1019
 
978
1020
 
@@ -263,8 +263,8 @@ def test_context_rejected_with_list_mode(capsys):
263
263
  )
264
264
  captured = capsys.readouterr()
265
265
  assert (
266
- "cannot be used with --list, --update, or --squash" in captured.out
267
- or "cannot be used with --list, --update, or --squash" in captured.err
266
+ "cannot be used with --list or --update" in captured.out
267
+ or "cannot be used with --list or --update" in captured.err
268
268
  )
269
269
  assert exc.value.exit_code == 1
270
270
 
@@ -282,29 +282,22 @@ def test_context_rejected_with_update_mode(capsys):
282
282
  )
283
283
  captured = capsys.readouterr()
284
284
  assert (
285
- "cannot be used with --list, --update, or --squash" in captured.out
286
- or "cannot be used with --list, --update, or --squash" in captured.err
285
+ "cannot be used with --list or --update" in captured.out
286
+ or "cannot be used with --list or --update" in captured.err
287
287
  )
288
288
  assert exc.value.exit_code == 1
289
289
 
290
290
 
291
- def test_context_rejected_with_squash_mode(capsys):
292
- """--context cannot be used with --squash."""
293
- with pytest.raises(typer.Exit) as exc:
294
- modes.validate_options(
295
- mode=Mode.SQUASH,
296
- stage_tracked=False,
297
- enable_debug=False,
298
- help_flag=False,
299
- version_flag=False,
300
- context="some context",
301
- )
302
- captured = capsys.readouterr()
303
- assert (
304
- "cannot be used with --list, --update, or --squash" in captured.out
305
- or "cannot be used with --list, --update, or --squash" in captured.err
291
+ def test_context_allowed_with_squash_mode():
292
+ """--context is allowed with SQUASH mode."""
293
+ modes.validate_options(
294
+ mode=Mode.SQUASH,
295
+ stage_tracked=False,
296
+ enable_debug=False,
297
+ help_flag=False,
298
+ version_flag=False,
299
+ context="Closes #42",
306
300
  )
307
- assert exc.value.exit_code == 1
308
301
 
309
302
 
310
303
  def test_context_allowed_with_commit_mode():
@@ -383,3 +383,31 @@ def test_squash_branch_with_squash_arg(mock_repo_root, mock_generator) -> None:
383
383
  ],
384
384
  any_order=False,
385
385
  )
386
+
387
+
388
+ def test_squash_branch_passes_context_to_generator(
389
+ mock_generator, mock_repo_root, clean_git_state
390
+ ):
391
+ """squash_branch() with context passes it to summarize_commit_history()."""
392
+
393
+ with (
394
+ patch("git_cai_cli.core.squash.find_git_root", return_value=mock_repo_root),
395
+ patch("subprocess.check_output", side_effect=clean_git_state),
396
+ patch(
397
+ "git_cai_cli.core.squash.load_config", return_value={"default": "openai"}
398
+ ),
399
+ patch("git_cai_cli.core.squash.load_token", return_value="token"),
400
+ patch(
401
+ "git_cai_cli.core.squash.CommitMessageGenerator",
402
+ return_value=mock_generator,
403
+ ),
404
+ patch("git_cai_cli.core.squash.get_git_editor", return_value="true"),
405
+ patch("git_cai_cli.core.squash.sha256_of_file", side_effect=["a", "b"]),
406
+ patch("subprocess.run", return_value=MagicMock(returncode=0)),
407
+ patch("git_cai_cli.core.squash._has_upstream", return_value=False),
408
+ patch("git_cai_cli.core.squash._has_commits", return_value=True),
409
+ ):
410
+ squash_branch(context="Closes #42")
411
+
412
+ call_args = mock_generator.summarize_commit_history.call_args
413
+ assert call_args[1].get("context") == "Closes #42"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes