overkill 0.8.2__tar.gz → 0.9.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.8.2 → overkill-0.9.0}/.overkillrc.example +3 -0
- {overkill-0.8.2 → overkill-0.9.0}/PKG-INFO +122 -5
- {overkill-0.8.2 → overkill-0.9.0}/README.md +120 -3
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-review.prompt.md +1 -1
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/codex-review.prompt.md +1 -1
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/gemini-review.prompt.md +1 -1
- {overkill-0.8.2 → overkill-0.9.0}/pyproject.toml +1 -1
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/agents.py +220 -27
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/cli.py +206 -3
- overkill-0.9.0/src/mr_overkill/commit_scope.py +125 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/git_ops.py +18 -2
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/loop_engine.py +106 -11
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/models.py +22 -0
- overkill-0.9.0/src/mr_overkill/review_loop.py +439 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/self_review.py +15 -3
- overkill-0.9.0/src/mr_overkill/wip_scope.py +439 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_agents.py +318 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_cli.py +319 -0
- overkill-0.9.0/tests/test_commit_scope.py +197 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_git_ops.py +96 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_loop_engine.py +313 -2
- overkill-0.9.0/tests/test_review_loop.py +1116 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_self_review.py +117 -0
- overkill-0.9.0/tests/test_wip_scope.py +693 -0
- {overkill-0.8.2 → overkill-0.9.0}/uv.lock +1 -1
- overkill-0.8.2/src/mr_overkill/review_loop.py +0 -65
- overkill-0.8.2/tests/test_review_loop.py +0 -225
- {overkill-0.8.2 → overkill-0.9.0}/.github/workflows/publish.yml +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/.github/workflows/test.yml +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/.gitignore +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/.python-version +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/.refactorsuggestrc.example +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/AGENTS.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/CLAUDE.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/GEMINI.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/LICENSE +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/install.sh +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-fix-execute.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-fix.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-fix-execute.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-fix.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-full.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-layer.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-micro.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-refactor-module.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/claude-self-review.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/codex-refactor-full.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/codex-refactor-layer.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/codex-refactor-micro.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/codex-refactor-module.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/gemini-refactor-full.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/gemini-refactor-layer.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/gemini-refactor-micro.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/active/gemini-refactor-module.prompt.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/reference/claude-code-review-plugin.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/reference/claude-security-review.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/prompts/reference/codex-review-original.md +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/__init__.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/__main__.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/budget/__init__.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/budget/claude.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/budget/codex.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/budget/gemini.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/budget_report.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/classify.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/data/__init__.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/data/review.schema.json +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/init.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/json_extract.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/refactor_suggest.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/reporting.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/resume.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/retry.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/time_utils.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/src/mr_overkill/two_step_fix.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/__init__.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/conftest.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_budget_claude.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_budget_codex.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_budget_gemini.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_budget_policy.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_budget_report.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_classify.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_init.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_integration.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_json_extract.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_refactor_suggest.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_reporting.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_resume.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_retry.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_time_utils.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/tests/test_two_step_fix.py +0 -0
- {overkill-0.8.2 → overkill-0.9.0}/uninstall.sh +0 -0
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
# Enable auto-commit of fixes (default: true)
|
|
18
18
|
# AUTO_COMMIT=true
|
|
19
19
|
|
|
20
|
+
# Push the review/* branch created by --commit (default: false — stays local)
|
|
21
|
+
# COMMIT_SCOPE_PUSH=false
|
|
22
|
+
|
|
20
23
|
# CI trigger policy for iteration commits (default: last-only)
|
|
21
24
|
# last-only — append "[skip ci]" to each iteration commit; push a single
|
|
22
25
|
# empty "chore: trigger CI" commit only when the loop ends
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: overkill
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
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
|
|
@@ -117,14 +117,31 @@ overkill refactor-suggest -n 1 --dry-run
|
|
|
117
117
|
overkill review-loop [OPTIONS]
|
|
118
118
|
|
|
119
119
|
Options:
|
|
120
|
-
-t, --target <
|
|
120
|
+
-t, --target <rev> Target to diff against (default: develop). Accepts any
|
|
121
|
+
git revision, not just a branch name: a SHA, a tag, or
|
|
122
|
+
HEAD~5 all work, so you can review "everything since
|
|
123
|
+
commit X" without opening a PR. A revision that moves
|
|
124
|
+
with HEAD is pinned to a SHA when the run starts, so
|
|
125
|
+
the loop's own fix commits cannot shrink the range.
|
|
126
|
+
--commit <rev> Review an already-merged commit instead of the branch
|
|
127
|
+
diff. Creates a review/<sha>-<ts> branch off HEAD and
|
|
128
|
+
applies fixes there; no PR is created. <rev> is a single
|
|
129
|
+
commit — ranges are not supported. Excludes -t.
|
|
130
|
+
--push Push the auto-created review branch (default: local only)
|
|
131
|
+
--wip Include uncommitted working-tree changes in the review.
|
|
132
|
+
With commits enabled they are parked in a scaffolding
|
|
133
|
+
commit that is unwound when the run finishes, so no
|
|
134
|
+
commit is left behind either way. Excludes --commit.
|
|
121
135
|
-n, --max-loop <N> Maximum review-fix iterations (required, unless --resume)
|
|
122
136
|
--max-subloop <N> Maximum self-review sub-iterations per fix (default: 4)
|
|
123
137
|
--no-self-review Disable self-review (equivalent to --max-subloop 0)
|
|
124
138
|
--dry-run Run review only, do not fix
|
|
125
139
|
--no-auto-commit Fix but do not commit/push (single iteration)
|
|
126
140
|
--resume Resume from a previously interrupted run (reuses existing logs)
|
|
127
|
-
--
|
|
141
|
+
--fix-nits Also flag nits and style issues during self-review
|
|
142
|
+
--context <text> Additional context for the reviewer (design intent,
|
|
143
|
+
constraints)
|
|
144
|
+
--reviewer-backend <be> Reviewer backend: claude|codex|gemini (default: codex)
|
|
128
145
|
--ci-trigger-mode <m> CI trigger policy: every|last-only|none (default: last-only).
|
|
129
146
|
'last-only' tags each iteration commit with [skip ci]
|
|
130
147
|
and pushes a single empty trigger commit on PASS —
|
|
@@ -142,8 +159,108 @@ Examples:
|
|
|
142
159
|
overkill review-loop --resume # resume an interrupted run
|
|
143
160
|
overkill review-loop -n 2 --reviewer-backend claude # use Claude as reviewer
|
|
144
161
|
overkill review-loop -n 10 --ci-trigger-mode last-only # CI fires once on PASS
|
|
162
|
+
|
|
163
|
+
# Review only what landed after a given commit, before opening a PR
|
|
164
|
+
overkill review-loop -t abc123 -n 3
|
|
165
|
+
overkill review-loop -t "$(git merge-base origin/develop HEAD)" -n 3
|
|
166
|
+
|
|
167
|
+
# Improve a commit that is already merged
|
|
168
|
+
overkill review-loop --commit abc123 -n 1 --dry-run # report only, no branch
|
|
169
|
+
overkill review-loop --commit abc123 -n 3 # fix on a review/* branch
|
|
170
|
+
|
|
171
|
+
# Review work you have not committed yet
|
|
172
|
+
overkill review-loop --wip -n 1 --dry-run # report only, nothing touched
|
|
173
|
+
overkill review-loop --wip -n 3 # fix it, still uncommitted at the end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Reviewing an already-merged commit
|
|
177
|
+
|
|
178
|
+
`--commit` exists for the case the branch diff cannot express: a change that
|
|
179
|
+
already landed, which you now want to improve.
|
|
180
|
+
|
|
181
|
+
1. The commit's diff is written to `.overkill/logs/scope.diff`. It is computed
|
|
182
|
+
against the commit's **first parent**, so merge commits produce a real patch
|
|
183
|
+
— `git show` prints nothing for those.
|
|
184
|
+
2. A `review/<sha>-<timestamp>` branch is created off your current HEAD and the
|
|
185
|
+
fixes are committed there. The branch stays local unless you pass `--push`,
|
|
186
|
+
and no PR is created or commented on.
|
|
187
|
+
3. The reviewer treats `scope.diff` as *scope only*. Since other commits may
|
|
188
|
+
have landed since, it must confirm each finding against the file's current
|
|
189
|
+
contents and cite current line numbers.
|
|
190
|
+
|
|
191
|
+
Run it from a clean, up-to-date checkout of the branch the commit lives on:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git switch main && git pull
|
|
195
|
+
overkill review-loop --commit abc123 -n 3
|
|
145
196
|
```
|
|
146
197
|
|
|
198
|
+
**After upgrading, re-run `overkill init`** in each repo — `--commit` and
|
|
199
|
+
`--wip` need the `${REVIEW_SCOPE_NOTE}` marker that the refreshed review prompts
|
|
200
|
+
carry, and the run aborts with an explanatory error if it is missing. Note that
|
|
201
|
+
`init` overwrites `.overkill/prompts/active/`, so back up any customised prompts
|
|
202
|
+
first.
|
|
203
|
+
|
|
204
|
+
### Reviewing work you have not committed yet
|
|
205
|
+
|
|
206
|
+
Without `--wip` the review scope is `git diff <target>...<current>` — committed
|
|
207
|
+
work only. A dirty tree is rejected outright, and under `--dry-run` it is
|
|
208
|
+
silently left out of scope. `--wip` pulls it in.
|
|
209
|
+
|
|
210
|
+
How it gets there depends on whether the run is allowed to commit:
|
|
211
|
+
|
|
212
|
+
| Command | Mechanism | Iterations | Commits left behind |
|
|
213
|
+
|---|---|---|---|
|
|
214
|
+
| `--wip --dry-run` | worktree diff written to `.overkill/logs/wip.diff` | 1 (review only) | none |
|
|
215
|
+
| `--wip --no-auto-commit` | same | 1 | none |
|
|
216
|
+
| `--wip` | scaffolding commit, unwound at the end | up to `-n` | none |
|
|
217
|
+
|
|
218
|
+
Both paths end the same way: your working tree is dirty again, with the fixes
|
|
219
|
+
applied on top of your own edits. Only the iteration count differs. Multiple
|
|
220
|
+
iterations need commits because the loop detects convergence from the commit
|
|
221
|
+
graph, so `--wip` parks your work in a throwaway commit, lets the loop run
|
|
222
|
+
against it unchanged, and then removes the scaffolding with
|
|
223
|
+
`git reset --mixed`.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
overkill review-loop --wip -n 3
|
|
227
|
+
git diff # your work plus the fixes, uncommitted
|
|
228
|
+
cat .overkill/logs/wip-fixes.diff # just what the loop changed
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Worth knowing before you use it:
|
|
232
|
+
|
|
233
|
+
- **Nothing is ever pushed** in `--wip` mode, and no PR is commented on. This is
|
|
234
|
+
not configurable — the scaffolding commit holds unfinished work.
|
|
235
|
+
- **`git add -A` sweeps in anything `.gitignore` does not cover.** The file list
|
|
236
|
+
is printed before the scaffolding commit is made. Nothing is pushed and the
|
|
237
|
+
commit is unwound, but check the list if you keep untracked secrets around.
|
|
238
|
+
- **A staged/unstaged split does not survive.** `git reset --mixed` leaves
|
|
239
|
+
everything unstaged.
|
|
240
|
+
- **If the run is interrupted the scaffolding stays.** The command to undo it is
|
|
241
|
+
printed at the start and the base commit is saved to
|
|
242
|
+
`.overkill/logs/wip-base.txt`; `--wip --resume` picks an interrupted run back
|
|
243
|
+
up, parking the work again if the scaffolding is already gone. A run that
|
|
244
|
+
already finished is left alone. Resume needs commits enabled — the other two
|
|
245
|
+
modes are a single pass with nothing to resume. A *fresh* `--wip` run refuses
|
|
246
|
+
to start on top of leftover scaffolding rather than nest a second commit on
|
|
247
|
+
it, which would strand the earlier draft on the branch — including when the
|
|
248
|
+
scaffolding sits behind fix commits the interrupted run already made. A
|
|
249
|
+
resume refuses too if you have committed normally on top of it, because
|
|
250
|
+
unwinding would rewind that commit into uncommitted changes.
|
|
251
|
+
- **A resumed run's `wip-fixes.diff` only covers the iterations after the
|
|
252
|
+
resume.** Re-parking folds the earlier attempt's fixes in with your own work,
|
|
253
|
+
so they cannot be told apart again; that attempt's diff is kept beside it as
|
|
254
|
+
`wip-fixes-<sha>.diff`.
|
|
255
|
+
- **Commit hooks are skipped** for the run's own commits. Work in progress
|
|
256
|
+
routinely fails hooks it will pass once finished, and every commit `--wip`
|
|
257
|
+
makes is torn down again.
|
|
258
|
+
- **An unfinished merge, rebase, cherry-pick or revert blocks the mode.** The
|
|
259
|
+
scaffolding commit would conclude the operation, and unwinding would then
|
|
260
|
+
reset past it.
|
|
261
|
+
- **New files are included.** They are staged as intent-to-add so the reviewer
|
|
262
|
+
can see them, then unstaged again.
|
|
263
|
+
|
|
147
264
|
## Usage: overkill refactor-suggest
|
|
148
265
|
|
|
149
266
|
Unlike `review-loop` which reviews diffs, `refactor-suggest` analyzes the **entire codebase** for refactoring opportunities at a chosen scope level.
|
|
@@ -164,7 +281,7 @@ Options:
|
|
|
164
281
|
--resume Resume from a previously interrupted run (reuses existing logs)
|
|
165
282
|
--with-review Run review-loop after PR creation (default: 4 iterations)
|
|
166
283
|
--with-review-loops <N> Set review-loop iteration count (implies --with-review)
|
|
167
|
-
--reviewer-backend <be> Reviewer backend: claude|codex (default: codex)
|
|
284
|
+
--reviewer-backend <be> Reviewer backend: claude|codex|gemini (default: codex)
|
|
168
285
|
--diagnostic-log Save full Claude event stream to sidecar files
|
|
169
286
|
--no-budget-gate Skip token-budget checks and run regardless
|
|
170
287
|
(same as OVERKILL_SKIP_BUDGET=1)
|
|
@@ -94,14 +94,31 @@ overkill refactor-suggest -n 1 --dry-run
|
|
|
94
94
|
overkill review-loop [OPTIONS]
|
|
95
95
|
|
|
96
96
|
Options:
|
|
97
|
-
-t, --target <
|
|
97
|
+
-t, --target <rev> Target to diff against (default: develop). Accepts any
|
|
98
|
+
git revision, not just a branch name: a SHA, a tag, or
|
|
99
|
+
HEAD~5 all work, so you can review "everything since
|
|
100
|
+
commit X" without opening a PR. A revision that moves
|
|
101
|
+
with HEAD is pinned to a SHA when the run starts, so
|
|
102
|
+
the loop's own fix commits cannot shrink the range.
|
|
103
|
+
--commit <rev> Review an already-merged commit instead of the branch
|
|
104
|
+
diff. Creates a review/<sha>-<ts> branch off HEAD and
|
|
105
|
+
applies fixes there; no PR is created. <rev> is a single
|
|
106
|
+
commit — ranges are not supported. Excludes -t.
|
|
107
|
+
--push Push the auto-created review branch (default: local only)
|
|
108
|
+
--wip Include uncommitted working-tree changes in the review.
|
|
109
|
+
With commits enabled they are parked in a scaffolding
|
|
110
|
+
commit that is unwound when the run finishes, so no
|
|
111
|
+
commit is left behind either way. Excludes --commit.
|
|
98
112
|
-n, --max-loop <N> Maximum review-fix iterations (required, unless --resume)
|
|
99
113
|
--max-subloop <N> Maximum self-review sub-iterations per fix (default: 4)
|
|
100
114
|
--no-self-review Disable self-review (equivalent to --max-subloop 0)
|
|
101
115
|
--dry-run Run review only, do not fix
|
|
102
116
|
--no-auto-commit Fix but do not commit/push (single iteration)
|
|
103
117
|
--resume Resume from a previously interrupted run (reuses existing logs)
|
|
104
|
-
--
|
|
118
|
+
--fix-nits Also flag nits and style issues during self-review
|
|
119
|
+
--context <text> Additional context for the reviewer (design intent,
|
|
120
|
+
constraints)
|
|
121
|
+
--reviewer-backend <be> Reviewer backend: claude|codex|gemini (default: codex)
|
|
105
122
|
--ci-trigger-mode <m> CI trigger policy: every|last-only|none (default: last-only).
|
|
106
123
|
'last-only' tags each iteration commit with [skip ci]
|
|
107
124
|
and pushes a single empty trigger commit on PASS —
|
|
@@ -119,8 +136,108 @@ Examples:
|
|
|
119
136
|
overkill review-loop --resume # resume an interrupted run
|
|
120
137
|
overkill review-loop -n 2 --reviewer-backend claude # use Claude as reviewer
|
|
121
138
|
overkill review-loop -n 10 --ci-trigger-mode last-only # CI fires once on PASS
|
|
139
|
+
|
|
140
|
+
# Review only what landed after a given commit, before opening a PR
|
|
141
|
+
overkill review-loop -t abc123 -n 3
|
|
142
|
+
overkill review-loop -t "$(git merge-base origin/develop HEAD)" -n 3
|
|
143
|
+
|
|
144
|
+
# Improve a commit that is already merged
|
|
145
|
+
overkill review-loop --commit abc123 -n 1 --dry-run # report only, no branch
|
|
146
|
+
overkill review-loop --commit abc123 -n 3 # fix on a review/* branch
|
|
147
|
+
|
|
148
|
+
# Review work you have not committed yet
|
|
149
|
+
overkill review-loop --wip -n 1 --dry-run # report only, nothing touched
|
|
150
|
+
overkill review-loop --wip -n 3 # fix it, still uncommitted at the end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Reviewing an already-merged commit
|
|
154
|
+
|
|
155
|
+
`--commit` exists for the case the branch diff cannot express: a change that
|
|
156
|
+
already landed, which you now want to improve.
|
|
157
|
+
|
|
158
|
+
1. The commit's diff is written to `.overkill/logs/scope.diff`. It is computed
|
|
159
|
+
against the commit's **first parent**, so merge commits produce a real patch
|
|
160
|
+
— `git show` prints nothing for those.
|
|
161
|
+
2. A `review/<sha>-<timestamp>` branch is created off your current HEAD and the
|
|
162
|
+
fixes are committed there. The branch stays local unless you pass `--push`,
|
|
163
|
+
and no PR is created or commented on.
|
|
164
|
+
3. The reviewer treats `scope.diff` as *scope only*. Since other commits may
|
|
165
|
+
have landed since, it must confirm each finding against the file's current
|
|
166
|
+
contents and cite current line numbers.
|
|
167
|
+
|
|
168
|
+
Run it from a clean, up-to-date checkout of the branch the commit lives on:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git switch main && git pull
|
|
172
|
+
overkill review-loop --commit abc123 -n 3
|
|
122
173
|
```
|
|
123
174
|
|
|
175
|
+
**After upgrading, re-run `overkill init`** in each repo — `--commit` and
|
|
176
|
+
`--wip` need the `${REVIEW_SCOPE_NOTE}` marker that the refreshed review prompts
|
|
177
|
+
carry, and the run aborts with an explanatory error if it is missing. Note that
|
|
178
|
+
`init` overwrites `.overkill/prompts/active/`, so back up any customised prompts
|
|
179
|
+
first.
|
|
180
|
+
|
|
181
|
+
### Reviewing work you have not committed yet
|
|
182
|
+
|
|
183
|
+
Without `--wip` the review scope is `git diff <target>...<current>` — committed
|
|
184
|
+
work only. A dirty tree is rejected outright, and under `--dry-run` it is
|
|
185
|
+
silently left out of scope. `--wip` pulls it in.
|
|
186
|
+
|
|
187
|
+
How it gets there depends on whether the run is allowed to commit:
|
|
188
|
+
|
|
189
|
+
| Command | Mechanism | Iterations | Commits left behind |
|
|
190
|
+
|---|---|---|---|
|
|
191
|
+
| `--wip --dry-run` | worktree diff written to `.overkill/logs/wip.diff` | 1 (review only) | none |
|
|
192
|
+
| `--wip --no-auto-commit` | same | 1 | none |
|
|
193
|
+
| `--wip` | scaffolding commit, unwound at the end | up to `-n` | none |
|
|
194
|
+
|
|
195
|
+
Both paths end the same way: your working tree is dirty again, with the fixes
|
|
196
|
+
applied on top of your own edits. Only the iteration count differs. Multiple
|
|
197
|
+
iterations need commits because the loop detects convergence from the commit
|
|
198
|
+
graph, so `--wip` parks your work in a throwaway commit, lets the loop run
|
|
199
|
+
against it unchanged, and then removes the scaffolding with
|
|
200
|
+
`git reset --mixed`.
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
overkill review-loop --wip -n 3
|
|
204
|
+
git diff # your work plus the fixes, uncommitted
|
|
205
|
+
cat .overkill/logs/wip-fixes.diff # just what the loop changed
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Worth knowing before you use it:
|
|
209
|
+
|
|
210
|
+
- **Nothing is ever pushed** in `--wip` mode, and no PR is commented on. This is
|
|
211
|
+
not configurable — the scaffolding commit holds unfinished work.
|
|
212
|
+
- **`git add -A` sweeps in anything `.gitignore` does not cover.** The file list
|
|
213
|
+
is printed before the scaffolding commit is made. Nothing is pushed and the
|
|
214
|
+
commit is unwound, but check the list if you keep untracked secrets around.
|
|
215
|
+
- **A staged/unstaged split does not survive.** `git reset --mixed` leaves
|
|
216
|
+
everything unstaged.
|
|
217
|
+
- **If the run is interrupted the scaffolding stays.** The command to undo it is
|
|
218
|
+
printed at the start and the base commit is saved to
|
|
219
|
+
`.overkill/logs/wip-base.txt`; `--wip --resume` picks an interrupted run back
|
|
220
|
+
up, parking the work again if the scaffolding is already gone. A run that
|
|
221
|
+
already finished is left alone. Resume needs commits enabled — the other two
|
|
222
|
+
modes are a single pass with nothing to resume. A *fresh* `--wip` run refuses
|
|
223
|
+
to start on top of leftover scaffolding rather than nest a second commit on
|
|
224
|
+
it, which would strand the earlier draft on the branch — including when the
|
|
225
|
+
scaffolding sits behind fix commits the interrupted run already made. A
|
|
226
|
+
resume refuses too if you have committed normally on top of it, because
|
|
227
|
+
unwinding would rewind that commit into uncommitted changes.
|
|
228
|
+
- **A resumed run's `wip-fixes.diff` only covers the iterations after the
|
|
229
|
+
resume.** Re-parking folds the earlier attempt's fixes in with your own work,
|
|
230
|
+
so they cannot be told apart again; that attempt's diff is kept beside it as
|
|
231
|
+
`wip-fixes-<sha>.diff`.
|
|
232
|
+
- **Commit hooks are skipped** for the run's own commits. Work in progress
|
|
233
|
+
routinely fails hooks it will pass once finished, and every commit `--wip`
|
|
234
|
+
makes is torn down again.
|
|
235
|
+
- **An unfinished merge, rebase, cherry-pick or revert blocks the mode.** The
|
|
236
|
+
scaffolding commit would conclude the operation, and unwinding would then
|
|
237
|
+
reset past it.
|
|
238
|
+
- **New files are included.** They are staged as intent-to-add so the reviewer
|
|
239
|
+
can see them, then unstaged again.
|
|
240
|
+
|
|
124
241
|
## Usage: overkill refactor-suggest
|
|
125
242
|
|
|
126
243
|
Unlike `review-loop` which reviews diffs, `refactor-suggest` analyzes the **entire codebase** for refactoring opportunities at a chosen scope level.
|
|
@@ -141,7 +258,7 @@ Options:
|
|
|
141
258
|
--resume Resume from a previously interrupted run (reuses existing logs)
|
|
142
259
|
--with-review Run review-loop after PR creation (default: 4 iterations)
|
|
143
260
|
--with-review-loops <N> Set review-loop iteration count (implies --with-review)
|
|
144
|
-
--reviewer-backend <be> Reviewer backend: claude|codex (default: codex)
|
|
261
|
+
--reviewer-backend <be> Reviewer backend: claude|codex|gemini (default: codex)
|
|
145
262
|
--diagnostic-log Save full Claude event stream to sidecar files
|
|
146
263
|
--no-budget-gate Skip token-budget checks and run regardless
|
|
147
264
|
(same as OVERKILL_SKIP_BUDGET=1)
|
|
@@ -16,6 +16,7 @@ from abc import ABC, abstractmethod
|
|
|
16
16
|
from importlib.resources import as_file, files
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
|
|
19
|
+
from mr_overkill import commit_scope, wip_scope
|
|
19
20
|
from mr_overkill.budget import SKIP_BUDGET_ENV_VAR, budget_gate_disabled
|
|
20
21
|
from mr_overkill.budget.claude import claude_budget_sufficient
|
|
21
22
|
from mr_overkill.budget.codex import codex_budget_sufficient
|
|
@@ -47,6 +48,211 @@ def _format_reviewer_context(raw: str) -> str:
|
|
|
47
48
|
return f"## Author Context\n\n{raw}"
|
|
48
49
|
|
|
49
50
|
|
|
51
|
+
_SCOPE_NOTE_MARKER = "${REVIEW_SCOPE_NOTE}"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Shared by both WIP mechanisms: the code under review is a draft, and the
|
|
55
|
+
# reviewer has to be told so or it will report the draft-ness as the defect.
|
|
56
|
+
# Neither mechanism hands over the draft alone: both artefacts also carry the
|
|
57
|
+
# author's own committed work on this branch, and that is finished code. So the
|
|
58
|
+
# subject names the draft portion and each caller carves the rest out.
|
|
59
|
+
def _wip_draft_calibration(subject: str) -> str:
|
|
60
|
+
"""Draft-vs-defect calibration, scoped to *subject*."""
|
|
61
|
+
return f"""
|
|
62
|
+
### This work is unfinished
|
|
63
|
+
|
|
64
|
+
{subject} has not been committed by the author, so judge it as a **draft**:
|
|
65
|
+
|
|
66
|
+
- Do flag defects in what is actually written — bugs, unsafe assumptions, \
|
|
67
|
+
resource leaks, debug statements or credentials left behind.
|
|
68
|
+
- Do **not** flag incompleteness itself. A half-implemented feature, a missing \
|
|
69
|
+
test for code still being written, or a function that is clearly the next thing \
|
|
70
|
+
the author will fill in is not a finding.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# The no-commit WIP mechanism leaves the author's draft uncommitted, so the
|
|
75
|
+
# self-review diff — ``git diff HEAD`` over the files the fixer touched — carries
|
|
76
|
+
# the draft alongside the fix. Unsaid, the self-reviewer reads the draft as the
|
|
77
|
+
# fixer's work: it reports the incompleteness, or calls the draft scope creep and
|
|
78
|
+
# the re-fix reverts work that exists nowhere but the working tree.
|
|
79
|
+
def _wip_self_review_note(scope_diff: Path) -> str:
|
|
80
|
+
"""Draft-vs-fix separation for the no-commit self-reviewer."""
|
|
81
|
+
return f"""
|
|
82
|
+
|
|
83
|
+
### The diff also contains the author's uncommitted draft
|
|
84
|
+
|
|
85
|
+
Nothing was committed before the fix, so the diff file shows the author's own work \
|
|
86
|
+
in progress as well as the fix. The draft as it stood **before any fix ran** was \
|
|
87
|
+
captured at `{scope_diff}`, so anything already written there is the author's rather \
|
|
88
|
+
than the fix. That capture was taken against a different base — match it by content, \
|
|
89
|
+
not by line number — and where a hunk mixes the two, the findings above say which \
|
|
90
|
+
part is the fix.
|
|
91
|
+
|
|
92
|
+
- Judge **only the fix**. Hunks that belong to the author's draft are out of scope.
|
|
93
|
+
- Do **not** report the draft's incompleteness, and do **not** report it as scope \
|
|
94
|
+
creep or ask for it to be reverted — it is not the fixer's work, and reverting it \
|
|
95
|
+
would destroy uncommitted work.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _format_wip_scope(config: LoopConfig) -> str:
|
|
100
|
+
"""Build the WIP-scope override block for whichever mechanism is in play."""
|
|
101
|
+
if config.scope_diff_file is not None:
|
|
102
|
+
# No-commit run: the branch diff shows only committed work, so it is
|
|
103
|
+
# actively misleading here — the scope artefact is the whole truth.
|
|
104
|
+
return f"""
|
|
105
|
+
> **REVIEW MODE: UNCOMMITTED WORK — read this first. It overrides the framing \
|
|
106
|
+
in the line above and re-scopes the Instructions below.**
|
|
107
|
+
|
|
108
|
+
The change under review is the author's **uncommitted working tree**, captured \
|
|
109
|
+
in full at `{config.scope_diff_file}`. Read that file first.
|
|
110
|
+
|
|
111
|
+
**Ignore the `git diff` command in the Instructions section.** It compares two \
|
|
112
|
+
commits, so it shows only the part of the work that happens to be committed \
|
|
113
|
+
already — reviewing it would silently skip everything the author is actually \
|
|
114
|
+
working on.
|
|
115
|
+
|
|
116
|
+
The scope diff was taken from the working tree as it exists right now, so its \
|
|
117
|
+
paths and line numbers are **current** and you may cite them directly.
|
|
118
|
+
|
|
119
|
+
It runs from this branch's fork point with `{config.target_branch}`, so it also \
|
|
120
|
+
contains commits the author already made here. `git diff \
|
|
121
|
+
{config.target_branch}...HEAD` prints exactly that committed portion — it is in \
|
|
122
|
+
scope too, but it is finished code, so the draft allowance below does not apply \
|
|
123
|
+
to it.
|
|
124
|
+
{_wip_draft_calibration("The uncommitted part of the change under review")}"""
|
|
125
|
+
|
|
126
|
+
# Scaffolding-commit run: the branch diff is exactly right, but the
|
|
127
|
+
# scaffolding commit's message would otherwise read as the change under
|
|
128
|
+
# review, and it sits on top of whatever the author has already committed
|
|
129
|
+
# on this branch rather than at the bottom of the diff.
|
|
130
|
+
return f"""
|
|
131
|
+
> **REVIEW MODE: UNCOMMITTED WORK — read this first.**
|
|
132
|
+
|
|
133
|
+
The commit on this branch whose message is `{wip_scope.SCAFFOLD_MESSAGE}` is not a \
|
|
134
|
+
change the author wrote a commit for. It is their **uncommitted work**, parked in \
|
|
135
|
+
a throwaway commit so that it can be reviewed and so that fixes have somewhere to \
|
|
136
|
+
land. It will be unwound when this run finishes. Review it exactly as if the \
|
|
137
|
+
author had committed it deliberately — it is the change under review.
|
|
138
|
+
|
|
139
|
+
Commits **before** it are the author's own committed work on this branch. They are \
|
|
140
|
+
in scope too, but they are finished code, so the draft allowance below does not \
|
|
141
|
+
apply to them. Commits **after** it are fixes an earlier iteration of this loop \
|
|
142
|
+
already applied.
|
|
143
|
+
{_wip_draft_calibration("The work parked in that commit")}"""
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _format_review_scope(config: LoopConfig, iteration: int) -> str:
|
|
147
|
+
"""Build the scope override block, or "" in normal branch-diff mode.
|
|
148
|
+
|
|
149
|
+
Empty-string-means-no-section, like ``EXTRA_REVIEW_GUIDELINES`` in the
|
|
150
|
+
self-review prompt. Note ``string.Template`` does not substitute
|
|
151
|
+
recursively, so every value here is interpolated in Python.
|
|
152
|
+
"""
|
|
153
|
+
sha = config.scope_commit
|
|
154
|
+
if not sha:
|
|
155
|
+
return _format_wip_scope(config) if config.wip else ""
|
|
156
|
+
|
|
157
|
+
diff_path = config.scope_diff_file
|
|
158
|
+
ancestry = ""
|
|
159
|
+
if not commit_scope.is_ancestor_of_head(sha):
|
|
160
|
+
ancestry = (
|
|
161
|
+
f"\n> WARNING: `{sha[:7]}` is **not an ancestor of HEAD**. Much of the "
|
|
162
|
+
"code it touched may not exist in the working tree at all. Report only "
|
|
163
|
+
"defects you can locate in a file that exists right now.\n"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if iteration <= 1:
|
|
167
|
+
fixes = (
|
|
168
|
+
"None yet — this is the first pass. The `git diff` command in the "
|
|
169
|
+
"Instructions section will print **nothing** on this iteration. That is "
|
|
170
|
+
"expected, it is not an error, and it is **not** the change under review."
|
|
171
|
+
)
|
|
172
|
+
else:
|
|
173
|
+
fixes = (
|
|
174
|
+
f"This is iteration {iteration}. Earlier iterations already produced fix "
|
|
175
|
+
"commits on this branch, and the `git diff` command in the Instructions "
|
|
176
|
+
"section prints **those fixes** — not the change under review. Use it to "
|
|
177
|
+
"(a) confirm which of your earlier findings are now resolved — **never "
|
|
178
|
+
"re-report a resolved finding** — and (b) look for new defects the fixes "
|
|
179
|
+
"themselves introduced.\n\nIf every earlier finding is resolved and you "
|
|
180
|
+
'find nothing new, return zero findings and `"patch is correct"`.'
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return f"""
|
|
184
|
+
> **REVIEW MODE: COMMIT SCOPE — read this first. It overrides the framing in the \
|
|
185
|
+
line above and re-scopes the Instructions and Review Guidelines below.**
|
|
186
|
+
|
|
187
|
+
You are **not** reviewing a proposed change. You are reviewing a change that was \
|
|
188
|
+
**already merged**:
|
|
189
|
+
|
|
190
|
+
- **Commit under review**: {commit_scope.commit_headline(sha)}
|
|
191
|
+
- **Its diff**: `{diff_path}`
|
|
192
|
+
{ancestry}
|
|
193
|
+
Read that diff file first. Do **not** try to reconstruct it with `git show` or \
|
|
194
|
+
`git diff` — it has already been generated correctly for you, including for merge \
|
|
195
|
+
commits (where `git show` prints nothing at all).
|
|
196
|
+
|
|
197
|
+
### The scope diff is historical — the code has moved on
|
|
198
|
+
|
|
199
|
+
Other commits have landed since. A line number, a function, or a whole file in the \
|
|
200
|
+
scope diff may no longer exist, may have been renamed, or may already have been fixed.
|
|
201
|
+
|
|
202
|
+
1. Use the scope diff **only** to decide *what is in scope*: which files and which \
|
|
203
|
+
behaviour the commit touched.
|
|
204
|
+
2. **The current contents of the working tree are the sole authority on whether a \
|
|
205
|
+
defect exists.** Before reporting anything, open the current file and confirm the \
|
|
206
|
+
defect is still there. If the current code already handles it, drop the finding.
|
|
207
|
+
3. Every `code_location` must be a **current** path with **current** line numbers, \
|
|
208
|
+
verified by reading the file. Line numbers copied from the scope diff will be wrong.
|
|
209
|
+
4. If a file in the scope diff no longer exists, skip it.
|
|
210
|
+
|
|
211
|
+
### Reading the guidelines below
|
|
212
|
+
|
|
213
|
+
Wherever a guideline says "this diff", read it as "the change made by \
|
|
214
|
+
`{sha[:7]}`, as it manifests in the code as it exists right now". The requirement \
|
|
215
|
+
that the issue be **introduced by this diff** still holds: do not flag pre-existing \
|
|
216
|
+
problems, and do not flag problems introduced by *later* commits.
|
|
217
|
+
|
|
218
|
+
### Fixes already applied on this branch
|
|
219
|
+
|
|
220
|
+
{fixes}
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _review_prompt_vars(config: LoopConfig, iteration: int) -> dict[str, str]:
|
|
225
|
+
"""Template variables shared by all three review prompts."""
|
|
226
|
+
return {
|
|
227
|
+
"CURRENT_BRANCH": config.current_branch,
|
|
228
|
+
"TARGET_BRANCH": config.target_branch,
|
|
229
|
+
"ITERATION": str(iteration),
|
|
230
|
+
"REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
|
|
231
|
+
"REVIEW_SCOPE_NOTE": _format_review_scope(config, iteration),
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _render_review_prompt(
|
|
236
|
+
prompt_file: Path, config: LoopConfig, iteration: int
|
|
237
|
+
) -> str | None:
|
|
238
|
+
"""Render a review prompt, or ``None`` if it cannot be used.
|
|
239
|
+
|
|
240
|
+
In a scoped mode a prompt that predates the feature would silently drop the
|
|
241
|
+
scope note and have the reviewer inspect the wrong diff — which reads as
|
|
242
|
+
"no findings" rather than as a failure. Refuse instead.
|
|
243
|
+
"""
|
|
244
|
+
raw = prompt_file.read_text(encoding="utf-8")
|
|
245
|
+
if (config.scope_commit or config.wip) and _SCOPE_NOTE_MARKER not in raw:
|
|
246
|
+
logger.error(
|
|
247
|
+
"Prompt %s predates scoped review support (no %s marker). "
|
|
248
|
+
"Run 'overkill init' to refresh the prompt templates.",
|
|
249
|
+
prompt_file,
|
|
250
|
+
_SCOPE_NOTE_MARKER,
|
|
251
|
+
)
|
|
252
|
+
return None
|
|
253
|
+
return string.Template(raw).safe_substitute(_review_prompt_vars(config, iteration))
|
|
254
|
+
|
|
255
|
+
|
|
50
256
|
# ── Review schema (single source of truth for structured output) ─────
|
|
51
257
|
|
|
52
258
|
|
|
@@ -217,15 +423,9 @@ class CodexReviewAgent(ReviewAgent):
|
|
|
217
423
|
logger.error("Review prompt not found: %s", prompt_file)
|
|
218
424
|
return False
|
|
219
425
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
prompt_text = tmpl.safe_substitute({
|
|
224
|
-
"CURRENT_BRANCH": config.current_branch,
|
|
225
|
-
"TARGET_BRANCH": config.target_branch,
|
|
226
|
-
"ITERATION": str(iteration),
|
|
227
|
-
"REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
|
|
228
|
-
})
|
|
426
|
+
prompt_text = _render_review_prompt(prompt_file, config, iteration)
|
|
427
|
+
if prompt_text is None:
|
|
428
|
+
return False
|
|
229
429
|
|
|
230
430
|
if not self._budget_fn("codex", config.budget_scope, 0):
|
|
231
431
|
raise BudgetTimeoutError(
|
|
@@ -323,15 +523,9 @@ class ClaudeReviewAgent(ReviewAgent):
|
|
|
323
523
|
logger.error("Review prompt not found: %s", prompt_file)
|
|
324
524
|
return False
|
|
325
525
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
prompt_text = tmpl.safe_substitute({
|
|
330
|
-
"CURRENT_BRANCH": config.current_branch,
|
|
331
|
-
"TARGET_BRANCH": config.target_branch,
|
|
332
|
-
"ITERATION": str(iteration),
|
|
333
|
-
"REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
|
|
334
|
-
})
|
|
526
|
+
prompt_text = _render_review_prompt(prompt_file, config, iteration)
|
|
527
|
+
if prompt_text is None:
|
|
528
|
+
return False
|
|
335
529
|
|
|
336
530
|
if not self._budget_fn("claude", config.budget_scope, 0):
|
|
337
531
|
raise BudgetTimeoutError(
|
|
@@ -426,15 +620,9 @@ class GeminiReviewAgent(ReviewAgent):
|
|
|
426
620
|
logger.error("Review prompt not found: %s", prompt_file)
|
|
427
621
|
return False
|
|
428
622
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
prompt_text = tmpl.safe_substitute({
|
|
433
|
-
"CURRENT_BRANCH": config.current_branch,
|
|
434
|
-
"TARGET_BRANCH": config.target_branch,
|
|
435
|
-
"ITERATION": str(iteration),
|
|
436
|
-
"REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
|
|
437
|
-
})
|
|
623
|
+
prompt_text = _render_review_prompt(prompt_file, config, iteration)
|
|
624
|
+
if prompt_text is None:
|
|
625
|
+
return False
|
|
438
626
|
|
|
439
627
|
if not self._budget_fn("gemini", config.budget_scope, 0):
|
|
440
628
|
raise BudgetTimeoutError(
|
|
@@ -591,6 +779,11 @@ class ClaudeSelfReviewAgent(SelfReviewAgent):
|
|
|
591
779
|
budget_scope=config.budget_scope,
|
|
592
780
|
dry_run=config.dry_run,
|
|
593
781
|
fix_nits=config.fix_nits,
|
|
782
|
+
scope_note=(
|
|
783
|
+
_wip_self_review_note(config.scope_diff_file)
|
|
784
|
+
if config.wip and config.scope_diff_file is not None
|
|
785
|
+
else ""
|
|
786
|
+
),
|
|
594
787
|
original_review_json=json.loads(review_json_str),
|
|
595
788
|
)
|
|
596
789
|
|