code-review-ai-cli 1.3.2__tar.gz → 1.3.3__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 (25) hide show
  1. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/PKG-INFO +1 -1
  2. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/PKG-INFO +1 -1
  3. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/pyproject.toml +1 -1
  4. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/llm_client.py +2 -2
  5. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/tfs_client.py +17 -15
  6. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_tfs_client.py +21 -3
  7. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/README.md +0 -0
  8. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/SOURCES.txt +0 -0
  9. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/dependency_links.txt +0 -0
  10. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/entry_points.txt +0 -0
  11. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/requires.txt +0 -0
  12. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/code_review_ai_cli.egg-info/top_level.txt +0 -0
  13. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/setup.cfg +0 -0
  14. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/__init__.py +0 -0
  15. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/ai_review.py +0 -0
  16. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/config.py +0 -0
  17. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/formatter.py +0 -0
  18. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/git_utils.py +0 -0
  19. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/prompts/config.yaml.template +0 -0
  20. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/src/prompts/review_prompt.md.template +0 -0
  21. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_ai_review.py +0 -0
  22. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_config.py +0 -0
  23. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_formatter.py +0 -0
  24. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_git_utils.py +0 -0
  25. {code_review_ai_cli-1.3.2 → code_review_ai_cli-1.3.3}/tests/test_llm_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-review-ai-cli
3
- Version: 1.3.2
3
+ Version: 1.3.3
4
4
  Summary: Automated AI-powered code review CLI for Azure DevOps / TFS Pull Requests
5
5
  License: MIT
6
6
  Keywords: code-review,ai,azure-devops,tfs,pull-request,llm
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-review-ai-cli
3
- Version: 1.3.2
3
+ Version: 1.3.3
4
4
  Summary: Automated AI-powered code review CLI for Azure DevOps / TFS Pull Requests
5
5
  License: MIT
6
6
  Keywords: code-review,ai,azure-devops,tfs,pull-request,llm
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-review-ai-cli"
7
- version = "1.3.2"
7
+ version = "1.3.3"
8
8
  description = "Automated AI-powered code review CLI for Azure DevOps / TFS Pull Requests"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -210,8 +210,8 @@ def get_scope_guidance(review_scope: str, language: str, structured: bool = Fals
210
210
  * Only added lines (``+``) appear in the diff section.
211
211
  * A ``### FULL_FILE_CONTEXT_START: <path> ###`` /
212
212
  ``### FULL_FILE_CONTEXT_END ###`` block is embedded in the payload for
213
- each changed file, containing the complete new-version file content as
214
- **read-only** background.
213
+ each changed file, containing the complete old-version (before changes)
214
+ file content as **read-only** background.
215
215
  * The review must focus **exclusively** on the changed lines (``+``); the
216
216
  full-file section exists only to prevent the model from hallucinating
217
217
  about the surrounding code.
@@ -300,17 +300,17 @@ class TFSClient:
300
300
  Gets the diff of a specific Pull Request.
301
301
 
302
302
  For ``diff_only`` scope (default), builds a standard unified diff for
303
- each changed file and appends the full new-version file content as a
304
- clearly-marked read-only block::
303
+ each changed file and appends the full old-version (target branch) file
304
+ content as a clearly-marked read-only block::
305
305
 
306
306
  ### FULL_FILE_CONTEXT_START: /path/to/file ###
307
- <full file content>
307
+ <full file content — before changes>
308
308
  ### FULL_FILE_CONTEXT_END ###
309
309
 
310
310
  This block is preserved by
311
311
  :py:meth:`GitUtils.filter_diff_additions_only` so that the LLM
312
- receives the surrounding context without being asked to review
313
- unchanged lines.
312
+ receives the pre-change context without treating already-changed lines
313
+ as established code.
314
314
 
315
315
  For ``full_code`` scope, only the new-version file content is sent
316
316
  (every line prefixed with ``+``), without a ``-`` baseline.
@@ -442,7 +442,7 @@ class TFSClient:
442
442
  from the source branch, then generates a standard unified diff with
443
443
  3 lines of context using :py:mod:`difflib`.
444
444
 
445
- After the diff lines, the **full new-version file content** is
445
+ After the diff lines, the **full old-version (target branch) file content** is
446
446
  appended as a read-only context block bounded by sentinel markers::
447
447
 
448
448
  ### FULL_FILE_CONTEXT_START: /path/to/file ###
@@ -451,8 +451,8 @@ class TFSClient:
451
451
 
452
452
  These markers are recognised by
453
453
  :py:meth:`GitUtils.filter_diff_additions_only`, which preserves every
454
- line inside the block. This lets the LLM understand surrounding code
455
- without being asked to review unchanged lines.
454
+ line inside the block. This lets the LLM understand the surrounding
455
+ code before the changes without being asked to review unchanged lines.
456
456
 
457
457
  Args:
458
458
  repository: Repository name.
@@ -465,7 +465,7 @@ class TFSClient:
465
465
 
466
466
  Returns:
467
467
  List of diff strings for this file, including the
468
- ``FULL_FILE_CONTEXT`` block when new content is available.
468
+ ``FULL_FILE_CONTEXT`` block when old content is available.
469
469
  """
470
470
  old_lines: list[str] = []
471
471
  new_lines: list[str] = []
@@ -518,13 +518,15 @@ class TFSClient:
518
518
  # so that filter_diff_by_extensions and _split_diff_sections work correctly.
519
519
  result = [f"diff --git a{original_path} b{file_path}"] + diff
520
520
 
521
- # Include full file content as read-only context for the LLM.
522
- # This section is preserved by filter_diff_additions_only and allows
523
- # the model to understand the surrounding code without reviewing
524
- # unchanged lines.
525
- if new_lines:
521
+ # Include old-version file content as read-only context for the LLM.
522
+ # Using the pre-change (target branch) content ensures the diff is the
523
+ # sole source of "what is new", preventing the LLM from treating
524
+ # already-changed lines as established code.
525
+ # delete is excluded: the diff already contains the full removed content.
526
+ # add is excluded automatically because old_lines is empty for new files.
527
+ if old_lines and change_type != "delete":
526
528
  result.append(f"### FULL_FILE_CONTEXT_START: {file_path} ###")
527
- result.extend(new_lines)
529
+ result.extend(old_lines)
528
530
  result.append("### FULL_FILE_CONTEXT_END ###")
529
531
 
530
532
  return result
@@ -354,7 +354,7 @@ def test_build_diff_parts_and_file_content(mocker) -> None:
354
354
  # ---------------------------------------------------------------------------
355
355
 
356
356
  def test_build_unified_diff_part_appends_full_file_context_block(mocker) -> None:
357
- """_build_unified_diff_part must append FULL_FILE_CONTEXT markers with the new file content."""
357
+ """_build_unified_diff_part must append FULL_FILE_CONTEXT markers with the old (target branch) file content."""
358
358
  client = TFSClient(make_tfs_config())
359
359
  mocker.patch(
360
360
  "src.tfs_client.TFSClient._get_file_content",
@@ -368,13 +368,31 @@ def test_build_unified_diff_part_appends_full_file_context_block(mocker) -> None
368
368
  joined = "\n".join(result)
369
369
 
370
370
  assert "### FULL_FILE_CONTEXT_START: /src/app.py ###" in joined
371
- assert "new line one" in joined
372
- assert "new line two" in joined
371
+ assert "old line" in joined
372
+ assert "new line one" not in joined.split("### FULL_FILE_CONTEXT_START")[1]
373
373
  assert "### FULL_FILE_CONTEXT_END ###" in joined
374
374
  # Context block must appear after the diff headers
375
375
  assert joined.index("### FULL_FILE_CONTEXT_START") > joined.index("diff --git")
376
376
 
377
377
 
378
+ def test_build_unified_diff_part_no_context_block_on_add(mocker) -> None:
379
+ """_build_unified_diff_part must NOT append a FULL_FILE_CONTEXT block for add (no old version exists)."""
380
+ client = TFSClient(make_tfs_config())
381
+ mocker.patch(
382
+ "src.tfs_client.TFSClient._get_file_content",
383
+ return_value="new content",
384
+ )
385
+
386
+ result = client._build_unified_diff_part(
387
+ "repo-a", "/src/new_file.py", "/src/new_file.py", "add",
388
+ "refs/heads/feature", "refs/heads/main",
389
+ )
390
+ joined = "\n".join(result)
391
+
392
+ assert "### FULL_FILE_CONTEXT_START" not in joined
393
+ assert "### FULL_FILE_CONTEXT_END" not in joined
394
+
395
+
378
396
  def test_build_unified_diff_part_no_context_block_on_delete(mocker) -> None:
379
397
  """_build_unified_diff_part must NOT append a FULL_FILE_CONTEXT block when change_type is delete."""
380
398
  client = TFSClient(make_tfs_config())