overkill 0.8.2__tar.gz → 0.8.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 (87) hide show
  1. {overkill-0.8.2 → overkill-0.8.3}/PKG-INFO +2 -2
  2. {overkill-0.8.2 → overkill-0.8.3}/pyproject.toml +1 -1
  3. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/self_review.py +10 -2
  4. {overkill-0.8.2 → overkill-0.8.3}/tests/test_self_review.py +60 -0
  5. {overkill-0.8.2 → overkill-0.8.3}/uv.lock +1 -1
  6. {overkill-0.8.2 → overkill-0.8.3}/.github/workflows/publish.yml +0 -0
  7. {overkill-0.8.2 → overkill-0.8.3}/.github/workflows/test.yml +0 -0
  8. {overkill-0.8.2 → overkill-0.8.3}/.gitignore +0 -0
  9. {overkill-0.8.2 → overkill-0.8.3}/.overkillrc.example +0 -0
  10. {overkill-0.8.2 → overkill-0.8.3}/.python-version +0 -0
  11. {overkill-0.8.2 → overkill-0.8.3}/.refactorsuggestrc.example +0 -0
  12. {overkill-0.8.2 → overkill-0.8.3}/AGENTS.md +0 -0
  13. {overkill-0.8.2 → overkill-0.8.3}/CLAUDE.md +0 -0
  14. {overkill-0.8.2 → overkill-0.8.3}/GEMINI.md +0 -0
  15. {overkill-0.8.2 → overkill-0.8.3}/LICENSE +0 -0
  16. {overkill-0.8.2 → overkill-0.8.3}/README.md +0 -0
  17. {overkill-0.8.2 → overkill-0.8.3}/install.sh +0 -0
  18. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-fix-execute.prompt.md +0 -0
  19. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-fix.prompt.md +0 -0
  20. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-fix-execute.prompt.md +0 -0
  21. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-fix.prompt.md +0 -0
  22. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-full.prompt.md +0 -0
  23. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-layer.prompt.md +0 -0
  24. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-micro.prompt.md +0 -0
  25. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-refactor-module.prompt.md +0 -0
  26. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-review.prompt.md +0 -0
  27. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/claude-self-review.prompt.md +0 -0
  28. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/codex-refactor-full.prompt.md +0 -0
  29. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/codex-refactor-layer.prompt.md +0 -0
  30. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/codex-refactor-micro.prompt.md +0 -0
  31. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/codex-refactor-module.prompt.md +0 -0
  32. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/codex-review.prompt.md +0 -0
  33. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/gemini-refactor-full.prompt.md +0 -0
  34. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/gemini-refactor-layer.prompt.md +0 -0
  35. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/gemini-refactor-micro.prompt.md +0 -0
  36. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/gemini-refactor-module.prompt.md +0 -0
  37. {overkill-0.8.2 → overkill-0.8.3}/prompts/active/gemini-review.prompt.md +0 -0
  38. {overkill-0.8.2 → overkill-0.8.3}/prompts/reference/claude-code-review-plugin.md +0 -0
  39. {overkill-0.8.2 → overkill-0.8.3}/prompts/reference/claude-security-review.md +0 -0
  40. {overkill-0.8.2 → overkill-0.8.3}/prompts/reference/codex-review-original.md +0 -0
  41. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/__init__.py +0 -0
  42. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/__main__.py +0 -0
  43. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/agents.py +0 -0
  44. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/budget/__init__.py +0 -0
  45. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/budget/claude.py +0 -0
  46. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/budget/codex.py +0 -0
  47. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/budget/gemini.py +0 -0
  48. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/budget_report.py +0 -0
  49. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/classify.py +0 -0
  50. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/cli.py +0 -0
  51. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/data/__init__.py +0 -0
  52. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/data/review.schema.json +0 -0
  53. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/git_ops.py +0 -0
  54. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/init.py +0 -0
  55. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/json_extract.py +0 -0
  56. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/loop_engine.py +0 -0
  57. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/models.py +0 -0
  58. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/refactor_suggest.py +0 -0
  59. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/reporting.py +0 -0
  60. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/resume.py +0 -0
  61. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/retry.py +0 -0
  62. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/review_loop.py +0 -0
  63. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/time_utils.py +0 -0
  64. {overkill-0.8.2 → overkill-0.8.3}/src/mr_overkill/two_step_fix.py +0 -0
  65. {overkill-0.8.2 → overkill-0.8.3}/tests/__init__.py +0 -0
  66. {overkill-0.8.2 → overkill-0.8.3}/tests/conftest.py +0 -0
  67. {overkill-0.8.2 → overkill-0.8.3}/tests/test_agents.py +0 -0
  68. {overkill-0.8.2 → overkill-0.8.3}/tests/test_budget_claude.py +0 -0
  69. {overkill-0.8.2 → overkill-0.8.3}/tests/test_budget_codex.py +0 -0
  70. {overkill-0.8.2 → overkill-0.8.3}/tests/test_budget_gemini.py +0 -0
  71. {overkill-0.8.2 → overkill-0.8.3}/tests/test_budget_policy.py +0 -0
  72. {overkill-0.8.2 → overkill-0.8.3}/tests/test_budget_report.py +0 -0
  73. {overkill-0.8.2 → overkill-0.8.3}/tests/test_classify.py +0 -0
  74. {overkill-0.8.2 → overkill-0.8.3}/tests/test_cli.py +0 -0
  75. {overkill-0.8.2 → overkill-0.8.3}/tests/test_git_ops.py +0 -0
  76. {overkill-0.8.2 → overkill-0.8.3}/tests/test_init.py +0 -0
  77. {overkill-0.8.2 → overkill-0.8.3}/tests/test_integration.py +0 -0
  78. {overkill-0.8.2 → overkill-0.8.3}/tests/test_json_extract.py +0 -0
  79. {overkill-0.8.2 → overkill-0.8.3}/tests/test_loop_engine.py +0 -0
  80. {overkill-0.8.2 → overkill-0.8.3}/tests/test_refactor_suggest.py +0 -0
  81. {overkill-0.8.2 → overkill-0.8.3}/tests/test_reporting.py +0 -0
  82. {overkill-0.8.2 → overkill-0.8.3}/tests/test_resume.py +0 -0
  83. {overkill-0.8.2 → overkill-0.8.3}/tests/test_retry.py +0 -0
  84. {overkill-0.8.2 → overkill-0.8.3}/tests/test_review_loop.py +0 -0
  85. {overkill-0.8.2 → overkill-0.8.3}/tests/test_time_utils.py +0 -0
  86. {overkill-0.8.2 → overkill-0.8.3}/tests/test_two_step_fix.py +0 -0
  87. {overkill-0.8.2 → overkill-0.8.3}/uninstall.sh +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: overkill
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: AI-powered code review loop — automates Codex/Gemini review + Claude fix cycles
5
5
  Project-URL: Repository, https://github.com/modocai/mr-overkill
6
6
  Project-URL: Issues, https://github.com/modocai/mr-overkill/issues
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "overkill"
3
- version = "0.8.2"
3
+ version = "0.8.3"
4
4
  description = "AI-powered code review loop — automates Codex/Gemini review + Claude fix cycles"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -278,14 +278,22 @@ def _generate_diff(
278
278
  check=False,
279
279
  )
280
280
 
281
+ # Paths go in argv after ``--``: unlike add/reset, ``git diff`` has no
282
+ # --pathspec-from-file option and exits 129 on it, which would silently
283
+ # write an empty diff and skip the self-review for every iteration.
281
284
  result = subprocess.run(
282
- ["git", "diff", "HEAD", "--pathspec-from-file=-"],
283
- input=pathspec,
285
+ ["git", "diff", "HEAD", "--", *changed_files],
284
286
  cwd=cwd,
285
287
  capture_output=True,
286
288
  text=True,
287
289
  check=False,
288
290
  )
291
+ if result.returncode != 0:
292
+ logger.warning(
293
+ "git diff failed (exit %d): %s",
294
+ result.returncode,
295
+ result.stderr.strip(),
296
+ )
289
297
  output.write_text(result.stdout, encoding="utf-8")
290
298
 
291
299
  # Undo intent-to-add
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json
6
+ import subprocess
6
7
  from pathlib import Path
7
8
  from unittest.mock import MagicMock, patch
8
9
 
@@ -10,6 +11,7 @@ from mr_overkill.models import WorktreeSnapshot
10
11
  from mr_overkill.self_review import (
11
12
  _FIX_NITS_GUIDELINES,
12
13
  _compute_fingerprint,
14
+ _generate_diff,
13
15
  self_review_subloop,
14
16
  )
15
17
 
@@ -449,3 +451,61 @@ class TestFixNitsGuidelines:
449
451
 
450
452
  assert len(captured_prompt) == 1
451
453
  assert "Fix nits" not in captured_prompt[0]
454
+
455
+
456
+ class TestGenerateDiff:
457
+ """Exercise _generate_diff against a real git repo.
458
+
459
+ Every other test in this module patches _generate_diff out, so the real
460
+ command line was never run: it passed --pathspec-from-file to ``git diff``,
461
+ which rejects the option, and the discarded stderr turned that into an
462
+ empty diff that skipped the self-review on every iteration.
463
+ """
464
+
465
+ def test_modified_tracked_file(self, tmp_git_repo: Path) -> None:
466
+ (tmp_git_repo / "README.md").write_text("# test\nsecond line\n")
467
+ output = tmp_git_repo / "out.diff"
468
+
469
+ _generate_diff(["README.md"], output, tmp_git_repo)
470
+
471
+ diff = output.read_text()
472
+ assert "+second line" in diff
473
+ assert "a/README.md" in diff
474
+
475
+ def test_untracked_file_included(self, tmp_git_repo: Path) -> None:
476
+ (tmp_git_repo / "new.py").write_text("print('hi')\n")
477
+ output = tmp_git_repo / "out.diff"
478
+
479
+ _generate_diff(["new.py"], output, tmp_git_repo)
480
+
481
+ assert "+print('hi')" in output.read_text()
482
+
483
+ def test_intent_to_add_is_undone(self, tmp_git_repo: Path) -> None:
484
+ """The untracked file must be left unstaged for the later commit step."""
485
+ (tmp_git_repo / "new.py").write_text("print('hi')\n")
486
+
487
+ _generate_diff(["new.py"], tmp_git_repo / "out.diff", tmp_git_repo)
488
+
489
+ staged = subprocess.run(
490
+ ["git", "diff", "--cached", "--name-only"],
491
+ cwd=tmp_git_repo,
492
+ capture_output=True,
493
+ text=True,
494
+ check=True,
495
+ )
496
+ assert staged.stdout.strip() == ""
497
+
498
+ def test_path_with_spaces(self, tmp_git_repo: Path) -> None:
499
+ (tmp_git_repo / "my file.txt").write_text("content\n")
500
+ output = tmp_git_repo / "out.diff"
501
+
502
+ _generate_diff(["my file.txt"], output, tmp_git_repo)
503
+
504
+ assert "+content" in output.read_text()
505
+
506
+ def test_no_changed_files_writes_empty(self, tmp_git_repo: Path) -> None:
507
+ output = tmp_git_repo / "out.diff"
508
+
509
+ _generate_diff([], output, tmp_git_repo)
510
+
511
+ assert output.read_text() == ""
@@ -247,7 +247,7 @@ wheels = [
247
247
 
248
248
  [[package]]
249
249
  name = "overkill"
250
- version = "0.8.2"
250
+ version = "0.8.3"
251
251
  source = { editable = "." }
252
252
 
253
253
  [package.dev-dependencies]
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
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