overkill 0.2.1__tar.gz → 0.3.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.
- {overkill-0.2.1 → overkill-0.3.0}/.gitignore +3 -1
- overkill-0.2.1/.reviewlooprc.example → overkill-0.3.0/.overkillrc.example +2 -2
- {overkill-0.2.1 → overkill-0.3.0}/PKG-INFO +15 -15
- {overkill-0.2.1 → overkill-0.3.0}/README.md +14 -14
- {overkill-0.2.1 → overkill-0.3.0}/bin/lib/common.sh +1 -1
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-review.prompt.md +20 -2
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/codex-review.prompt.md +15 -6
- {overkill-0.2.1 → overkill-0.3.0}/pyproject.toml +2 -2
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/__main__.py +2 -2
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/cli.py +89 -13
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/git_ops.py +5 -2
- overkill-0.3.0/src/mr_overkill/init.py +214 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/loop_engine.py +14 -1
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/refactor_suggest.py +11 -1
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/self_review.py +1 -1
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_cli.py +4 -4
- overkill-0.3.0/tests/test_init.py +161 -0
- {overkill-0.2.1 → overkill-0.3.0}/uninstall.sh +32 -3
- {overkill-0.2.1 → overkill-0.3.0}/uv.lock +1 -1
- overkill-0.2.1/src/mr_overkill/init.py +0 -142
- overkill-0.2.1/tests/test_init.py +0 -110
- {overkill-0.2.1 → overkill-0.3.0}/.github/workflows/publish.yml +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/.github/workflows/test.yml +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/.python-version +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/.refactorsuggestrc.example +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/AGENTS.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/CLAUDE.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/GEMINI.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/LICENSE +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/lib/check-claude-limit.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/lib/check-codex-limit.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/lib/retry.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/lib/self-review.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/refactor-suggest.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/bin/review-loop.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/install.sh +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-fix-execute.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-fix.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-fix-execute.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-fix.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-full.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-layer.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-micro.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-refactor-module.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/claude-self-review.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/codex-refactor-full.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/codex-refactor-layer.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/codex-refactor-micro.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/active/codex-refactor-module.prompt.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/reference/claude-code-review-plugin.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/reference/claude-security-review.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/prompts/reference/codex-review-original.md +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/__init__.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/agents.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/budget/__init__.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/budget/claude.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/budget/codex.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/budget_report.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/classify.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/data/__init__.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/json_extract.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/models.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/reporting.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/resume.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/retry.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/review_loop.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/time_utils.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/src/mr_overkill/two_step_fix.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/test/refactor-suggest.bats +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/test/test_helper.bash +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/__init__.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/conftest.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_agents.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_budget_claude.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_budget_codex.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_budget_policy.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_budget_report.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_classify.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_git_ops.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_integration.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_json_extract.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_loop_engine.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_refactor_suggest.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_reporting.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_resume.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_retry.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_review_loop.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_self_review.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_time_utils.py +0 -0
- {overkill-0.2.1 → overkill-0.3.0}/tests/test_two_step_fix.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# .
|
|
2
|
-
#
|
|
1
|
+
# .overkillrc — project-level configuration for overkill review-loop
|
|
2
|
+
# Place this file in .overkill/.overkillrc and customize.
|
|
3
3
|
# CLI arguments always take precedence over these values.
|
|
4
4
|
|
|
5
5
|
# Target branch to diff against (default: develop)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: overkill
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: AI-powered code review loop — automates Codex 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
|
|
@@ -161,7 +161,7 @@ Examples:
|
|
|
161
161
|
|
|
162
162
|
## Usage: overkill init
|
|
163
163
|
|
|
164
|
-
Initialize `.
|
|
164
|
+
Initialize `.overkill/` in a project directory. Safe to re-run — prompts are refreshed, user-edited configs are preserved.
|
|
165
165
|
|
|
166
166
|
```
|
|
167
167
|
overkill init [TARGET_DIR] # default: current directory
|
|
@@ -170,9 +170,9 @@ overkill init [TARGET_DIR] # default: current directory
|
|
|
170
170
|
Creates:
|
|
171
171
|
|
|
172
172
|
```
|
|
173
|
-
.
|
|
173
|
+
.overkill/
|
|
174
174
|
├── prompts/active/ # 10 prompt templates
|
|
175
|
-
├── .
|
|
175
|
+
├── .overkillrc # review-loop config
|
|
176
176
|
├── .refactorsuggestrc # refactor-suggest config
|
|
177
177
|
├── logs/ # runtime logs
|
|
178
178
|
│ └── refactor/ # refactor-suggest logs
|
|
@@ -207,9 +207,9 @@ Recommended workflow: start with `--dry-run` to review findings, then re-run wit
|
|
|
207
207
|
|
|
208
208
|
## Configuration
|
|
209
209
|
|
|
210
|
-
After running `overkill init`, config files live in `.
|
|
210
|
+
After running `overkill init`, config files live in `.overkill/`:
|
|
211
211
|
|
|
212
|
-
### .
|
|
212
|
+
### .overkill/.overkillrc
|
|
213
213
|
|
|
214
214
|
```bash
|
|
215
215
|
TARGET_BRANCH="main"
|
|
@@ -220,9 +220,9 @@ REVIEWER_BACKEND="codex" # or "claude"
|
|
|
220
220
|
PROMPTS_DIR="./custom-prompts"
|
|
221
221
|
```
|
|
222
222
|
|
|
223
|
-
See `.
|
|
223
|
+
See `.overkill/.overkillrc` for all available options.
|
|
224
224
|
|
|
225
|
-
### .
|
|
225
|
+
### .overkill/.refactorsuggestrc
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
228
|
SCOPE="auto"
|
|
@@ -243,7 +243,7 @@ PROMPTS_DIR="./custom-prompts"
|
|
|
243
243
|
|
|
244
244
|
```
|
|
245
245
|
1. Check prerequisites (git, codex, claude, jq, envsubst, target branch)
|
|
246
|
-
2. Create .
|
|
246
|
+
2. Create .overkill/logs/ directory
|
|
247
247
|
3. Loop (iteration 1..N):
|
|
248
248
|
a. Generate diff: git diff $TARGET...$CURRENT
|
|
249
249
|
b. Empty diff → exit
|
|
@@ -258,14 +258,14 @@ PROMPTS_DIR="./custom-prompts"
|
|
|
258
258
|
h. Push to remote (updates PR)
|
|
259
259
|
i. Post review/fix/self-review summary as PR comment
|
|
260
260
|
j. Next iteration reviews the updated committed state
|
|
261
|
-
4. Write summary to .
|
|
261
|
+
4. Write summary to .overkill/logs/summary.md
|
|
262
262
|
```
|
|
263
263
|
|
|
264
264
|
## Output Files
|
|
265
265
|
|
|
266
|
-
All logs are git-ignored by default (inside `.
|
|
266
|
+
All logs are git-ignored by default (inside `.overkill/`).
|
|
267
267
|
|
|
268
|
-
### review-loop logs (`.
|
|
268
|
+
### review-loop logs (`.overkill/logs/`)
|
|
269
269
|
|
|
270
270
|
| File | Description |
|
|
271
271
|
|------|-------------|
|
|
@@ -277,7 +277,7 @@ All logs are git-ignored by default (inside `.review-loop/`).
|
|
|
277
277
|
| `refix-N-M.md` | Claude re-fix log (iteration N, sub-iteration M) |
|
|
278
278
|
| `summary.md` | Final summary with status and per-iteration results |
|
|
279
279
|
|
|
280
|
-
### refactor-suggest logs (`.
|
|
280
|
+
### refactor-suggest logs (`.overkill/logs/refactor/`)
|
|
281
281
|
|
|
282
282
|
| File | Description |
|
|
283
283
|
|------|-------------|
|
|
@@ -316,7 +316,7 @@ Go/no-go decision based on current usage percentage:
|
|
|
316
316
|
|
|
317
317
|
## Customizing Prompts
|
|
318
318
|
|
|
319
|
-
Edit the templates in `.
|
|
319
|
+
Edit the templates in `.overkill/prompts/active/`.
|
|
320
320
|
|
|
321
321
|
### review-loop prompts
|
|
322
322
|
|
|
@@ -364,7 +364,7 @@ The loop terminates when any of these occur:
|
|
|
364
364
|
|
|
365
365
|
```bash
|
|
366
366
|
# Quick — just nuke the directory
|
|
367
|
-
rm -rf .
|
|
367
|
+
rm -rf .overkill
|
|
368
368
|
|
|
369
369
|
# Also remove the Python package
|
|
370
370
|
pip uninstall overkill # or: uv tool uninstall overkill / pipx uninstall overkill
|
|
@@ -139,7 +139,7 @@ Examples:
|
|
|
139
139
|
|
|
140
140
|
## Usage: overkill init
|
|
141
141
|
|
|
142
|
-
Initialize `.
|
|
142
|
+
Initialize `.overkill/` in a project directory. Safe to re-run — prompts are refreshed, user-edited configs are preserved.
|
|
143
143
|
|
|
144
144
|
```
|
|
145
145
|
overkill init [TARGET_DIR] # default: current directory
|
|
@@ -148,9 +148,9 @@ overkill init [TARGET_DIR] # default: current directory
|
|
|
148
148
|
Creates:
|
|
149
149
|
|
|
150
150
|
```
|
|
151
|
-
.
|
|
151
|
+
.overkill/
|
|
152
152
|
├── prompts/active/ # 10 prompt templates
|
|
153
|
-
├── .
|
|
153
|
+
├── .overkillrc # review-loop config
|
|
154
154
|
├── .refactorsuggestrc # refactor-suggest config
|
|
155
155
|
├── logs/ # runtime logs
|
|
156
156
|
│ └── refactor/ # refactor-suggest logs
|
|
@@ -185,9 +185,9 @@ Recommended workflow: start with `--dry-run` to review findings, then re-run wit
|
|
|
185
185
|
|
|
186
186
|
## Configuration
|
|
187
187
|
|
|
188
|
-
After running `overkill init`, config files live in `.
|
|
188
|
+
After running `overkill init`, config files live in `.overkill/`:
|
|
189
189
|
|
|
190
|
-
### .
|
|
190
|
+
### .overkill/.overkillrc
|
|
191
191
|
|
|
192
192
|
```bash
|
|
193
193
|
TARGET_BRANCH="main"
|
|
@@ -198,9 +198,9 @@ REVIEWER_BACKEND="codex" # or "claude"
|
|
|
198
198
|
PROMPTS_DIR="./custom-prompts"
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
-
See `.
|
|
201
|
+
See `.overkill/.overkillrc` for all available options.
|
|
202
202
|
|
|
203
|
-
### .
|
|
203
|
+
### .overkill/.refactorsuggestrc
|
|
204
204
|
|
|
205
205
|
```bash
|
|
206
206
|
SCOPE="auto"
|
|
@@ -221,7 +221,7 @@ PROMPTS_DIR="./custom-prompts"
|
|
|
221
221
|
|
|
222
222
|
```
|
|
223
223
|
1. Check prerequisites (git, codex, claude, jq, envsubst, target branch)
|
|
224
|
-
2. Create .
|
|
224
|
+
2. Create .overkill/logs/ directory
|
|
225
225
|
3. Loop (iteration 1..N):
|
|
226
226
|
a. Generate diff: git diff $TARGET...$CURRENT
|
|
227
227
|
b. Empty diff → exit
|
|
@@ -236,14 +236,14 @@ PROMPTS_DIR="./custom-prompts"
|
|
|
236
236
|
h. Push to remote (updates PR)
|
|
237
237
|
i. Post review/fix/self-review summary as PR comment
|
|
238
238
|
j. Next iteration reviews the updated committed state
|
|
239
|
-
4. Write summary to .
|
|
239
|
+
4. Write summary to .overkill/logs/summary.md
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
## Output Files
|
|
243
243
|
|
|
244
|
-
All logs are git-ignored by default (inside `.
|
|
244
|
+
All logs are git-ignored by default (inside `.overkill/`).
|
|
245
245
|
|
|
246
|
-
### review-loop logs (`.
|
|
246
|
+
### review-loop logs (`.overkill/logs/`)
|
|
247
247
|
|
|
248
248
|
| File | Description |
|
|
249
249
|
|------|-------------|
|
|
@@ -255,7 +255,7 @@ All logs are git-ignored by default (inside `.review-loop/`).
|
|
|
255
255
|
| `refix-N-M.md` | Claude re-fix log (iteration N, sub-iteration M) |
|
|
256
256
|
| `summary.md` | Final summary with status and per-iteration results |
|
|
257
257
|
|
|
258
|
-
### refactor-suggest logs (`.
|
|
258
|
+
### refactor-suggest logs (`.overkill/logs/refactor/`)
|
|
259
259
|
|
|
260
260
|
| File | Description |
|
|
261
261
|
|------|-------------|
|
|
@@ -294,7 +294,7 @@ Go/no-go decision based on current usage percentage:
|
|
|
294
294
|
|
|
295
295
|
## Customizing Prompts
|
|
296
296
|
|
|
297
|
-
Edit the templates in `.
|
|
297
|
+
Edit the templates in `.overkill/prompts/active/`.
|
|
298
298
|
|
|
299
299
|
### review-loop prompts
|
|
300
300
|
|
|
@@ -342,7 +342,7 @@ The loop terminates when any of these occur:
|
|
|
342
342
|
|
|
343
343
|
```bash
|
|
344
344
|
# Quick — just nuke the directory
|
|
345
|
-
rm -rf .
|
|
345
|
+
rm -rf .overkill
|
|
346
346
|
|
|
347
347
|
# Also remove the Python package
|
|
348
348
|
pip uninstall overkill # or: uv tool uninstall overkill / pipx uninstall overkill
|
|
@@ -277,7 +277,7 @@ _changed_files_since_snapshot() {
|
|
|
277
277
|
_out=$(mktemp)
|
|
278
278
|
_git_all_dirty_nul | while IFS= read -r -d '' _f; do
|
|
279
279
|
[[ -n "$_f" ]] || continue
|
|
280
|
-
[[ "$_f" == .review-loop/logs/* ]] && continue
|
|
280
|
+
[[ "$_f" == .overkill/logs/* || "$_f" == .review-loop/logs/* ]] && continue
|
|
281
281
|
if [[ -f "$_f" ]]; then
|
|
282
282
|
_cur_hash=$(git hash-object "$_f" 2>/dev/null || echo UNHASHABLE)
|
|
283
283
|
if [[ -x "$_f" ]]; then _cur_mode="100755"; else _cur_mode="100644"; fi
|
|
@@ -8,15 +8,23 @@ You are a code reviewer analyzing a proposed change.
|
|
|
8
8
|
|
|
9
9
|
## Instructions
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Start by running the following command to get the diff:
|
|
12
12
|
|
|
13
13
|
```
|
|
14
14
|
git diff ${TARGET_BRANCH}...${CURRENT_BRANCH}
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Then **actively explore the codebase** to understand context before flagging issues:
|
|
18
|
+
|
|
19
|
+
- Use `Read` to examine surrounding code when a change touches a function or module.
|
|
20
|
+
- Use `Grep` to check if a pattern, variable, or function is used elsewhere before calling it dead code or flagging a naming issue.
|
|
21
|
+
- Use `Glob` to find related files (e.g. tests, configs) that may clarify intent.
|
|
22
|
+
|
|
17
23
|
Review the diff according to the guidelines below.
|
|
18
24
|
|
|
19
|
-
## Review Guidelines
|
|
25
|
+
## Review Guidelines — HIGH SIGNAL ONLY
|
|
26
|
+
|
|
27
|
+
We only want findings where you are confident the issue is real. **If you are not certain an issue is real, do not flag it.** False positives erode trust and waste reviewer time.
|
|
20
28
|
|
|
21
29
|
1. Only flag issues the original author would fix if they knew about them.
|
|
22
30
|
2. The issue must be **introduced by this diff** — do not flag pre-existing problems.
|
|
@@ -24,6 +32,16 @@ Review the diff according to the guidelines below.
|
|
|
24
32
|
4. Do not flag trivial style issues unless they obscure meaning or violate documented standards.
|
|
25
33
|
5. Do not speculate — you must identify the exact code location and explain why it is a problem.
|
|
26
34
|
6. If this is iteration > 1, focus on whether issues from prior reviews have been properly fixed, and identify any new issues introduced by the fixes.
|
|
35
|
+
7. **Only flag issues where your confidence is >= 0.85.** If you cannot reach that threshold after investigating, do not include the finding.
|
|
36
|
+
|
|
37
|
+
### Do NOT flag (false positive filter)
|
|
38
|
+
|
|
39
|
+
- Pre-existing issues not introduced by this diff.
|
|
40
|
+
- Something that appears to be a bug but is actually correct when you read the surrounding code.
|
|
41
|
+
- Pedantic nitpicks that a senior engineer would not flag in a real review.
|
|
42
|
+
- Issues that a linter or formatter will catch — do not run the linter to verify.
|
|
43
|
+
- Potential issues that depend on specific inputs or state that are not demonstrated in the diff.
|
|
44
|
+
- General code quality concerns (e.g. lack of test coverage, general security hygiene) unless they are concretely exploitable.
|
|
27
45
|
|
|
28
46
|
## Priority Levels
|
|
29
47
|
|
|
@@ -20,10 +20,16 @@ Review the diff according to the guidelines below.
|
|
|
20
20
|
|
|
21
21
|
1. Only flag issues the original author would fix if they knew about them.
|
|
22
22
|
2. The issue must be **introduced by this diff** — do not flag pre-existing problems.
|
|
23
|
-
3. The issue must
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
26
|
-
6.
|
|
23
|
+
3. The issue must meaningfully impact the accuracy, performance, security, or maintainability of the code.
|
|
24
|
+
4. The issue must be discrete, actionable, and concretely provable.
|
|
25
|
+
5. Fixing the bug does not demand a level of rigor not present in the rest of the codebase (e.g. one doesn't need detailed comments and input validation in a repository of one-off scripts).
|
|
26
|
+
6. The bug does not rely on unstated assumptions about the codebase or author's intent.
|
|
27
|
+
7. It is not enough to speculate that a change may disrupt another part of the codebase — you must identify the other parts of the code that are provably affected.
|
|
28
|
+
8. The bug is clearly not just an intentional change by the original author.
|
|
29
|
+
9. Do not flag trivial style issues unless they obscure meaning or violate documented standards.
|
|
30
|
+
10. If this is iteration > 1, focus on whether issues from prior reviews have been properly fixed, and identify any new issues introduced by the fixes.
|
|
31
|
+
|
|
32
|
+
Output all findings that the original author would fix if they knew about them. If there is no finding that a person would definitely want to fix, prefer outputting no findings. Do not stop at the first qualifying finding — continue until you've listed every qualifying finding.
|
|
27
33
|
|
|
28
34
|
## Priority Levels
|
|
29
35
|
|
|
@@ -36,9 +42,12 @@ Review the diff according to the guidelines below.
|
|
|
36
42
|
|
|
37
43
|
- One comment per distinct issue.
|
|
38
44
|
- Brief (at most 1 paragraph body).
|
|
39
|
-
- Clearly state the scenarios
|
|
40
|
-
-
|
|
45
|
+
- Clearly state the scenarios, environments, or inputs required for the bug to manifest.
|
|
46
|
+
- Appropriately communicate severity — do not overclaim. Immediately indicate if the issue's severity depends on specific conditions.
|
|
47
|
+
- The comment should be written such that the original author can immediately grasp the idea without close reading.
|
|
48
|
+
- Matter-of-fact tone, no flattery. Avoid "Great job …", "Thanks for …".
|
|
41
49
|
- Code snippets max 3 lines, wrapped in markdown code tags.
|
|
50
|
+
- Use ```suggestion blocks only for concrete replacement code (minimal lines; no commentary inside the block). Preserve exact leading whitespace.
|
|
42
51
|
|
|
43
52
|
## Output Format
|
|
44
53
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "overkill"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "AI-powered code review loop — automates Codex review + Claude fix cycles"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -36,7 +36,7 @@ packages = ["src/mr_overkill"]
|
|
|
36
36
|
|
|
37
37
|
[tool.hatch.build.targets.wheel.force-include]
|
|
38
38
|
"prompts/active" = "mr_overkill/data/prompts/active"
|
|
39
|
-
".
|
|
39
|
+
".overkillrc.example" = "mr_overkill/data/.overkillrc.example"
|
|
40
40
|
".refactorsuggestrc.example" = "mr_overkill/data/.refactorsuggestrc.example"
|
|
41
41
|
|
|
42
42
|
[tool.pytest.ini_options]
|
|
@@ -24,7 +24,7 @@ def main() -> None:
|
|
|
24
24
|
print(
|
|
25
25
|
"Usage: overkill <command>\n\n"
|
|
26
26
|
"Commands:\n"
|
|
27
|
-
" init Initialize .
|
|
27
|
+
" init Initialize .overkill/ in a project\n"
|
|
28
28
|
" review-loop Run AI review-fix loop\n"
|
|
29
29
|
" refactor-suggest Run AI refactoring suggestions\n"
|
|
30
30
|
" check-budget Show token budget usage summary",
|
|
@@ -43,7 +43,7 @@ def main() -> None:
|
|
|
43
43
|
|
|
44
44
|
p = argparse.ArgumentParser(
|
|
45
45
|
prog="overkill init",
|
|
46
|
-
description="Initialize .
|
|
46
|
+
description="Initialize .overkill/ in a project",
|
|
47
47
|
)
|
|
48
48
|
p.add_argument("target", nargs="?", default=".", help="Target directory")
|
|
49
49
|
init_args = p.parse_args()
|
|
@@ -7,6 +7,7 @@ mirroring the CLI interface of the bash scripts.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import argparse
|
|
10
|
+
import logging
|
|
10
11
|
import re
|
|
11
12
|
import subprocess
|
|
12
13
|
from dataclasses import dataclass
|
|
@@ -59,18 +60,45 @@ def _load_rc_file(rc_name: str) -> dict[str, str]:
|
|
|
59
60
|
return {}
|
|
60
61
|
|
|
61
62
|
git_root = Path(result.stdout.strip())
|
|
62
|
-
rc_path = git_root / ".
|
|
63
|
+
rc_path = git_root / ".overkill" / rc_name
|
|
63
64
|
if not rc_path.is_file():
|
|
64
|
-
# Fall back to the legacy
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
# Fall back to the legacy .review-loop/ location
|
|
66
|
+
legacy_dir = git_root / ".review-loop" / rc_name
|
|
67
|
+
# Also check for legacy .reviewlooprc name in .review-loop/
|
|
68
|
+
legacy_old_name = (
|
|
69
|
+
git_root / ".review-loop" / ".reviewlooprc"
|
|
70
|
+
if rc_name == ".overkillrc" else None
|
|
71
|
+
)
|
|
72
|
+
# Legacy repo-root name: .overkillrc was .reviewlooprc
|
|
73
|
+
legacy_root_name = ".reviewlooprc" if rc_name == ".overkillrc" else rc_name
|
|
74
|
+
legacy_root = git_root / legacy_root_name
|
|
75
|
+
if legacy_dir.is_file():
|
|
76
|
+
logging.getLogger(__name__).warning(
|
|
77
|
+
"%s found at .review-loop/ (legacy location). "
|
|
78
|
+
"Please run 'overkill init' to migrate to .overkill/",
|
|
79
|
+
rc_name,
|
|
80
|
+
)
|
|
81
|
+
rc_path = legacy_dir
|
|
82
|
+
elif legacy_old_name and legacy_old_name.is_file():
|
|
83
|
+
logging.getLogger(__name__).warning(
|
|
84
|
+
".reviewlooprc found at .review-loop/ (legacy location). "
|
|
85
|
+
"Please run 'overkill init' to migrate to .overkill/.overkillrc",
|
|
86
|
+
)
|
|
87
|
+
rc_path = legacy_old_name
|
|
88
|
+
elif (git_root / rc_name).is_file():
|
|
68
89
|
logging.getLogger(__name__).warning(
|
|
69
90
|
"%s found at repo root (legacy location). "
|
|
70
|
-
"Please move it to .
|
|
91
|
+
"Please move it to .overkill/%s",
|
|
71
92
|
rc_name, rc_name,
|
|
72
93
|
)
|
|
73
|
-
rc_path =
|
|
94
|
+
rc_path = git_root / rc_name
|
|
95
|
+
elif legacy_root.is_file():
|
|
96
|
+
logging.getLogger(__name__).warning(
|
|
97
|
+
"%s found at repo root (legacy location). "
|
|
98
|
+
"Please move it to .overkill/%s",
|
|
99
|
+
legacy_root_name, rc_name,
|
|
100
|
+
)
|
|
101
|
+
rc_path = legacy_root
|
|
74
102
|
else:
|
|
75
103
|
return {}
|
|
76
104
|
|
|
@@ -118,7 +146,33 @@ def _resolve_prompts_dir(prompts_dir: str) -> Path:
|
|
|
118
146
|
check=False,
|
|
119
147
|
)
|
|
120
148
|
if result.returncode == 0:
|
|
121
|
-
|
|
149
|
+
git_root = Path(result.stdout.strip())
|
|
150
|
+
resolved = git_root / prompts_dir
|
|
151
|
+
# Legacy fallback: .overkill/... → .review-loop/...
|
|
152
|
+
if not resolved.is_dir() and ".overkill/" in prompts_dir:
|
|
153
|
+
legacy = git_root / prompts_dir.replace(
|
|
154
|
+
".overkill/", ".review-loop/", 1
|
|
155
|
+
)
|
|
156
|
+
if legacy.is_dir():
|
|
157
|
+
logging.getLogger(__name__).warning(
|
|
158
|
+
"Prompts dir found at %s (legacy location). "
|
|
159
|
+
"Please run 'overkill init' to migrate to .overkill/",
|
|
160
|
+
legacy,
|
|
161
|
+
)
|
|
162
|
+
return legacy
|
|
163
|
+
# Inverse fallback: .review-loop/... → .overkill/...
|
|
164
|
+
if not resolved.is_dir() and ".review-loop/" in prompts_dir:
|
|
165
|
+
migrated = git_root / prompts_dir.replace(
|
|
166
|
+
".review-loop/", ".overkill/", 1
|
|
167
|
+
)
|
|
168
|
+
if migrated.is_dir():
|
|
169
|
+
logging.getLogger(__name__).warning(
|
|
170
|
+
"Prompts dir migrated to %s. "
|
|
171
|
+
"Please update PROMPTS_DIR in your rc file.",
|
|
172
|
+
migrated,
|
|
173
|
+
)
|
|
174
|
+
return migrated
|
|
175
|
+
return resolved
|
|
122
176
|
return p
|
|
123
177
|
|
|
124
178
|
|
|
@@ -249,7 +303,7 @@ def parse_review_loop_args(
|
|
|
249
303
|
args = parser.parse_args(argv)
|
|
250
304
|
|
|
251
305
|
# Load rc file defaults
|
|
252
|
-
rc = _load_rc_file(".
|
|
306
|
+
rc = _load_rc_file(".overkillrc")
|
|
253
307
|
|
|
254
308
|
# Resolve values with precedence: CLI > rc file > defaults
|
|
255
309
|
target = args.target or rc.get("TARGET_BRANCH", "develop")
|
|
@@ -292,7 +346,7 @@ def parse_review_loop_args(
|
|
|
292
346
|
budget_scope_str = rc.get("BUDGET_SCOPE", "module")
|
|
293
347
|
|
|
294
348
|
prompts_dir = _resolve_prompts_dir(
|
|
295
|
-
rc.get("PROMPTS_DIR", ".
|
|
349
|
+
rc.get("PROMPTS_DIR", ".overkill/prompts/active")
|
|
296
350
|
)
|
|
297
351
|
|
|
298
352
|
current_branch = _detect_current_branch()
|
|
@@ -306,7 +360,18 @@ def parse_review_loop_args(
|
|
|
306
360
|
check=False,
|
|
307
361
|
)
|
|
308
362
|
git_root = Path(result.stdout.strip()) if result.returncode == 0 else Path(".")
|
|
309
|
-
log_dir = git_root / ".
|
|
363
|
+
log_dir = git_root / ".overkill" / "logs"
|
|
364
|
+
if not log_dir.is_dir():
|
|
365
|
+
legacy_log = git_root / ".review-loop" / "logs"
|
|
366
|
+
if legacy_log.is_dir():
|
|
367
|
+
log_dir = legacy_log
|
|
368
|
+
|
|
369
|
+
# In mixed-state repos, fall back to legacy logs when resume metadata
|
|
370
|
+
# is missing from the preferred directory.
|
|
371
|
+
if args.resume and not (log_dir / "max-loop.txt").is_file():
|
|
372
|
+
legacy_log = git_root / ".review-loop" / "logs"
|
|
373
|
+
if (legacy_log / "max-loop.txt").is_file():
|
|
374
|
+
log_dir = legacy_log
|
|
310
375
|
|
|
311
376
|
# Restore saved values on resume when not explicitly given
|
|
312
377
|
if args.resume:
|
|
@@ -539,7 +604,7 @@ def parse_refactor_suggest_args(
|
|
|
539
604
|
budget_scope_str = rc.get("BUDGET_SCOPE", "module")
|
|
540
605
|
|
|
541
606
|
prompts_dir = _resolve_prompts_dir(
|
|
542
|
-
rc.get("PROMPTS_DIR", ".
|
|
607
|
+
rc.get("PROMPTS_DIR", ".overkill/prompts/active")
|
|
543
608
|
)
|
|
544
609
|
|
|
545
610
|
current_branch = _detect_current_branch()
|
|
@@ -555,7 +620,18 @@ def parse_refactor_suggest_args(
|
|
|
555
620
|
Path(result.stdout.strip()) if result.returncode == 0
|
|
556
621
|
else Path(".")
|
|
557
622
|
)
|
|
558
|
-
log_dir = git_root / ".
|
|
623
|
+
log_dir = git_root / ".overkill" / "logs" / "refactor"
|
|
624
|
+
if not log_dir.is_dir():
|
|
625
|
+
legacy_log = git_root / ".review-loop" / "logs" / "refactor"
|
|
626
|
+
if legacy_log.is_dir():
|
|
627
|
+
log_dir = legacy_log
|
|
628
|
+
|
|
629
|
+
# In mixed-state repos, fall back to legacy logs when resume metadata
|
|
630
|
+
# is missing from the preferred directory.
|
|
631
|
+
if args.resume and not (log_dir / "max-loop.txt").is_file():
|
|
632
|
+
legacy_log = git_root / ".review-loop" / "logs" / "refactor"
|
|
633
|
+
if (legacy_log / "max-loop.txt").is_file():
|
|
634
|
+
log_dir = legacy_log
|
|
559
635
|
|
|
560
636
|
# Restore saved values on resume when not explicitly given
|
|
561
637
|
if args.resume:
|
|
@@ -100,12 +100,14 @@ def changed_files_since_snapshot(
|
|
|
100
100
|
snapshot: list[WorktreeSnapshot],
|
|
101
101
|
cwd: Path | None = None,
|
|
102
102
|
exclude_prefix: str | None = None,
|
|
103
|
+
exclude_prefixes: tuple[str, ...] | None = None,
|
|
103
104
|
) -> list[str]:
|
|
104
105
|
"""Compare current dirty files against a snapshot.
|
|
105
106
|
|
|
106
107
|
Returns list of file paths that changed (new, modified, or deleted).
|
|
107
108
|
Uses a dict for O(1) lookups (vs O(n²) awk in bash).
|
|
108
109
|
"""
|
|
110
|
+
_prefixes = exclude_prefixes or ((exclude_prefix,) if exclude_prefix else ())
|
|
109
111
|
snap_map: dict[str, tuple[str, str]] = {
|
|
110
112
|
s.path: (s.file_hash, s.mode) for s in snapshot
|
|
111
113
|
}
|
|
@@ -113,7 +115,7 @@ def changed_files_since_snapshot(
|
|
|
113
115
|
changed: list[str] = []
|
|
114
116
|
|
|
115
117
|
for f in git_all_dirty(cwd):
|
|
116
|
-
if
|
|
118
|
+
if _prefixes and any(f.startswith(p) for p in _prefixes):
|
|
117
119
|
continue
|
|
118
120
|
|
|
119
121
|
fpath = base / f
|
|
@@ -210,7 +212,8 @@ def commit_and_push(
|
|
|
210
212
|
Raises ``RuntimeError`` if ``git commit`` or ``git push`` fails.
|
|
211
213
|
"""
|
|
212
214
|
changed = changed_files_since_snapshot(
|
|
213
|
-
snapshot, cwd=cwd,
|
|
215
|
+
snapshot, cwd=cwd,
|
|
216
|
+
exclude_prefixes=(".overkill/logs/", ".review-loop/logs/"),
|
|
214
217
|
)
|
|
215
218
|
if not changed:
|
|
216
219
|
logger.info("No file changes after fix — nothing to commit.")
|