See [docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md](docs/prs/2026-10-06-PR%2332-hints-hold-the-merge.md).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; review requested from mi; merge scheduled for when the checks succeed
With [gate] hints_hold_merge (default on), a GREEN review with unresolved bot line comments approves
but schedules no merge and cancels an earlier one; a review after all hints are resolved schedules it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md:68
hint model recommends merge with caution
Findings
[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently at werkrevisor/cli.py:608-611, ORANGE, as a line comment
[low] Document omits the cancel-failure and missing-comment behaviour at docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md:68, hint, as a line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 69656, calls 1, tokens in 68642 / out 536 (reasoning included in out), duration 18.3 s, cost 0.1426 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5632, cost 0.0002 USD, finding judge `jev-1.13.0` calls 1, tokens in 1662, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `6732eda3b4ab70d6fb322ec42021511d9818b3eb` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:6732eda3b4ab70d6fb322ec42021511d9818b3eb -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>6732eda</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1363">the result for <code>23983b0</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/cli.py:608-611
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md:68
- **hint** model recommends merge with caution
### Findings
1. **[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently** at `werkrevisor/cli.py:608-611`, ORANGE, as a line comment
2. **[low] Document omits the cancel-failure and missing-comment behaviour** at `docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md:68`, hint, as a line comment
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 69656, calls 1, tokens in 68642 / out 536 (reasoning included in out), duration 18.3 s, cost 0.1426 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5632, cost 0.0002 USD, finding judge `jev-1.13.0` calls 1, tokens in 1662, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `6732eda3b4ab70d6fb322ec42021511d9818b3eb` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for 6732eda3b4ab70d6fb322ec42021511d9818b3eb.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `6732eda3b4ab70d6fb322ec42021511d9818b3eb`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:6732eda3b4ab70d6fb322ec42021511d9818b3eb -->
[low] Document omits the cancel-failure and missing-comment behaviour (werkrevisor)
hint
The Solution says the gate note goes into the result comment, but the code writes it into the comment only on the first review of a head (existing is None). On a restart with open hints the note appears only in the commit status. The document should state this or the code should match it.
**[low] Document omits the cancel-failure and missing-comment behaviour** (werkrevisor)
hint
The Solution says the gate note goes into the result comment, but the code writes it into the comment only on the first review of a head (`existing is None`). On a restart with open hints the note appears only in the commit status. The document should state this or the code should match it.
Fixed in 23983b0: the PR doc says that the gate note, also a failed cancel, goes into the commit status and the result comment, and that a restart posts a short comment.
Fixed in 23983b0: the PR doc says that the gate note, also a failed cancel, goes into the commit status and the result comment, and that a restart posts a short comment.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently (werkrevisor)
ORANGE; Jev: real 0.80, severity 3.0 of 3
In the already-reviewed path (existing is not None), _publish returns the existing comment and decision.held is true, but _note_hold is skipped because of existing is None. The result comment then never states the hold on a restart, although the commit status does. Separately, _hold_merge swallows a failed cancel (non-404) only into the note. For a restart of an unresolved head the note is not in the comment, so a failed cancel stays invisible in the result comment and a merge for the earlier head may still happen.
**[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently** (werkrevisor)
ORANGE; Jev: real 0.80, severity 3.0 of 3
In the already-reviewed path (`existing is not None`), `_publish` returns the existing comment and `decision.held` is true, but `_note_hold` is skipped because of `existing is None`. The result comment then never states the hold on a restart, although the commit status does. Separately, `_hold_merge` swallows a failed cancel (non-404) only into the note. For a restart of an unresolved head the note is not in the comment, so a failed cancel stays invisible in the result comment and a merge for the earlier head may still happen.
Fixed in 23983b0: a restarted review posts its gate note as a short PR comment, since the result comment names the first review; a failed cancel is part of that note and, since a66d56e, also fails the gate check (exit code 10).
Fixed in 23983b0: a restarted review posts its gate note as a short PR comment, since the result comment names the first review; a failed cancel is part of that note and, since a66d56e, also fails the gate check (exit code 10).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-code marked this conversation as resolved
ai-reviewer
scheduled this pull request to auto merge when all checks succeed 2026-10-06 15:22:19 +02:00
ai-reviewer
requested review from mi 2026-10-06 15:22:19 +02:00
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 2 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:610-615, werkrevisor/cli.py:518-527
hint model recommends merge with caution
Findings
[medium] Hold does not use the hints of the current review when line comments are refused at werkrevisor/cli.py:491-494, ORANGE, as a line comment
[medium] Hold also fires for hints of a restarted review without gate comment on first review at werkrevisor/cli.py:610-615, hint, still open in an earlier line comment
[low] Cancel also runs for a PR that never had a merge scheduled at werkrevisor/cli.py:518-527, hint, as a line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 71155, calls 1, tokens in 70148 / out 842 (reasoning included in out), duration 14.3 s, cost 0.1487 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5658, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3458, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `23983b00a606a328f481577092e14d1aef19dedd` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:23983b00a606a328f481577092e14d1aef19dedd -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>23983b0</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1368">the result for <code>f11a884</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/cli.py:491-494
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 2 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:610-615, werkrevisor/cli.py:518-527
- **hint** model recommends merge with caution
### Findings
1. **[medium] Hold does not use the hints of the current review when line comments are refused** at `werkrevisor/cli.py:491-494`, ORANGE, as a line comment
2. **[medium] Hold also fires for hints of a restarted review without gate comment on first review** at `werkrevisor/cli.py:610-615`, hint, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1357)
3. **[low] Cancel also runs for a PR that never had a merge scheduled** at `werkrevisor/cli.py:518-527`, hint, as a line comment
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 71155, calls 1, tokens in 70148 / out 842 (reasoning included in out), duration 14.3 s, cost 0.1487 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5658, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3458, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `23983b00a606a328f481577092e14d1aef19dedd` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for 23983b00a606a328f481577092e14d1aef19dedd.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `23983b00a606a328f481577092e14d1aef19dedd`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:23983b00a606a328f481577092e14d1aef19dedd -->
[medium] Hold does not use the hints of the current review when line comments are refused (werkrevisor)
ORANGE; Jev: real 0.89, severity 3.0 of 3
_open_bot_line_comments counts only unresolved bot line comments with position > 0. If Gitea refused the line comments (line_comments_refused), the findings are carried in the result comment and no line comments exist, so the count is 0 and the merge is scheduled right after the GREEN review. The hold then silently does not apply to the very hints the PR is meant to protect. This is a narrow case (a 400/422 on line comments), but it reproduces the original problem of PR#30.
**[medium] Hold does not use the hints of the current review when line comments are refused** (werkrevisor)
ORANGE; Jev: real 0.89, severity 3.0 of 3
`_open_bot_line_comments` counts only unresolved bot line comments with `position > 0`. If Gitea refused the line comments (`line_comments_refused`), the findings are carried in the result comment and no line comments exist, so the count is 0 and the merge is scheduled right after the GREEN review. The hold then silently does not apply to the very hints the PR is meant to protect. This is a narrow case (a 400/422 on line comments), but it reproduces the original problem of PR#30.
Fixed in f11a884: findings of this review that are no line comment, e.g. refused by Gitea, count as open hints too; a restart releases them, since it reuses the verdict without findings. Test test_hints_refused_as_line_comments_hold_the_merge_too, red without the fix.
The later finding in this thread, "cancel failure fails the check but the approval stands": intended. The approval stands, but the required gate check fails, and Gitea's "merge when checks succeed" waits for it; a network error outside GiteaError ends the run as ERROR, which fails the check too.
Fixed in f11a884: findings of this review that are no line comment, e.g. refused by Gitea, count as open hints too; a restart releases them, since it reuses the verdict without findings. Test `test_hints_refused_as_line_comments_hold_the_merge_too`, red without the fix.
The later finding in this thread, "cancel failure fails the check but the approval stands": intended. The approval stands, but the required gate check fails, and Gitea's "merge when checks succeed" waits for it; a network error outside `GiteaError` ends the run as ERROR, which fails the check too.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
[low] Cancel also runs for a PR that never had a merge scheduled (werkrevisor)
hint
_hold_merge always sends DELETE /pulls/{n}/merge and treats 404 as "none scheduled". This is the documented behavior, but any other error status (e.g. 405 or 409 on some Gitea versions when nothing is scheduled) is reported in the gate note as "could not be cancelled", which can mislead the author when there is nothing to cancel.
**[low] Cancel also runs for a PR that never had a merge scheduled** (werkrevisor)
hint
`_hold_merge` always sends `DELETE /pulls/{n}/merge` and treats 404 as "none scheduled". This is the documented behavior, but any other error status (e.g. 405 or 409 on some Gitea versions when nothing is scheduled) is reported in the gate note as "could not be cancelled", which can mislead the author when there is nothing to cancel.
Not changed in its first form: Gitea 1.27 answers 404 when no merge is scheduled, which counts as success; any other error fails the gate check since a66d56e, on purpose, since an uncancelled merge would merge the held head.
The later finding in this thread, "hold merge can be released when review comments fail to read", was real: fixed in 3729f3e. Unreadable line comments now hold the merge and fail the gate check. Test test_unreadable_hints_hold_the_merge, red without the fix.
Not changed in its first form: Gitea 1.27 answers 404 when no merge is scheduled, which counts as success; any other error fails the gate check since a66d56e, on purpose, since an uncancelled merge would merge the held head.
The later finding in this thread, "hold merge can be released when review comments fail to read", was real: fixed in 3729f3e. Unreadable line comments now hold the merge and fail the gate check. Test `test_unreadable_hints_hold_the_merge`, red without the fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 2 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:619-622, werkrevisor/cli.py:525-534
hint model recommends merge with caution
Findings
[medium] Reused review reads findings from the wrong state at werkrevisor/cli.py:518-522, ORANGE, still open in an earlier line comment
[medium] Restart comment posted on every GREEN rerun at werkrevisor/cli.py:619-622, hint, as a line comment
[low] Failed cancel gives a misleading note at werkrevisor/cli.py:525-534, hint, as a line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 72155, calls 1, tokens in 71087 / out 709 (reasoning included in out), duration 12.6 s, cost 0.1493 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5697, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3387, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `f11a8841686e9e44ccdb1b69bec9d26abef9f323` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:f11a8841686e9e44ccdb1b69bec9d26abef9f323 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>f11a884</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1373">the result for <code>a66d56e</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/cli.py:518-522
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 2 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:619-622, werkrevisor/cli.py:525-534
- **hint** model recommends merge with caution
### Findings
1. **[medium] Reused review reads findings from the wrong state** at `werkrevisor/cli.py:518-522`, ORANGE, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1365)
2. **[medium] Restart comment posted on every GREEN rerun** at `werkrevisor/cli.py:619-622`, hint, as a line comment
3. **[low] Failed cancel gives a misleading note** at `werkrevisor/cli.py:525-534`, hint, as a line comment
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 72155, calls 1, tokens in 71087 / out 709 (reasoning included in out), duration 12.6 s, cost 0.1493 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5697, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3387, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `f11a8841686e9e44ccdb1b69bec9d26abef9f323` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for f11a8841686e9e44ccdb1b69bec9d26abef9f323.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `f11a8841686e9e44ccdb1b69bec9d26abef9f323`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:f11a8841686e9e44ccdb1b69bec9d26abef9f323 -->
[low] Failed cancel gives a misleading note (werkrevisor)
hint
_hold_merge only cancels and returns a note. If the cancel fails with something other than 404, the merge scheduled earlier stays active and will merge the head even though the note says the merge waits. The note does name the failure, but the exit code stays 0 and the status stays green. The operator has to read the note to see that the hold failed.
**[low] Failed cancel gives a misleading note** (werkrevisor)
hint
`_hold_merge` only cancels and returns a note. If the cancel fails with something other than 404, the merge scheduled earlier stays active and will merge the head even though the note says the merge waits. The note does name the failure, but the exit code stays 0 and the status stays green. The operator has to read the note to see that the hold failed.
Fixed in a66d56e: a failed cancel ends the review with exit code 10, so the failed gate check stops the merge scheduled earlier. Test test_a_failed_cancel_is_named, red without the fix.
Fixed in a66d56e: a failed cancel ends the review with exit code 10, so the failed gate check stops the merge scheduled earlier. Test `test_a_failed_cancel_is_named`, red without the fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
[medium] Restart comment posted on every GREEN rerun (werkrevisor)
hint; Jev: real 0.78, severity 1.3 of 3
The elif branch posts a new "review restarted" comment on every rerun of a GREEN head when automerge and hints_hold_merge are on. That includes the case where nothing changed and the merge was already scheduled, so each rerun adds a comment. Posting only when the gate note differs from the previous state, or only for a hold or a first schedule, would avoid the noise.
**[medium] Restart comment posted on every GREEN rerun** (werkrevisor)
hint; Jev: real 0.78, severity 1.3 of 3
The `elif` branch posts a new "review restarted" comment on every rerun of a GREEN head when `automerge` and `hints_hold_merge` are on. That includes the case where nothing changed and the merge was already scheduled, so each rerun adds a comment. Posting only when the gate note differs from the previous state, or only for a hold or a first schedule, would avoid the noise.
Fixed in a66d56e: a restart comments only when the merge still waits or is newly scheduled; "merge already scheduled" stays silent. Test test_a_restart_comments_only_a_change_of_the_merge.
The later findings in this thread (a comment on each restart with open hints): intended, see the answer in the thread of 1380.
Fixed in a66d56e: a restart comments only when the merge still waits or is newly scheduled; "merge already scheduled" stays silent. Test `test_a_restart_comments_only_a_change_of_the_merge`.
The later findings in this thread (a comment on each restart with open hints): intended, see the answer in the thread of 1380.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:621-624
hint model recommends merge with caution
Findings
[medium] hints_hold_merge not validated and not repository-restricted at werkrevisor/config.py:175-176, ORANGE, as a line comment
[medium] Cancel failure fails the check but approval already stands, and a 404 on cancel is not distinguished from a failed network call at werkrevisor/cli.py:493-495, ORANGE, still open in an earlier line comment
[medium] Restart with held merge is not retried when the hold persists and an earlier hold comment exists at werkrevisor/cli.py:621-624, hint, still open in an earlier line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 73120, calls 1, tokens in 72069 / out 824 (reasoning included in out), duration 13.3 s, cost 0.1524 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 3, tokens in 4723, cost 0.0002 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `a66d56e5b063f4fe95c46fe48ebb81e2486a611e` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:a66d56e5b063f4fe95c46fe48ebb81e2486a611e -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>a66d56e</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1377">the result for <code>602663a</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 2 finding(s) that Jev rates as probably real and severe: werkrevisor/config.py:175-176, werkrevisor/cli.py:493-495
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:621-624
- **hint** model recommends merge with caution
### Findings
1. **[medium] hints_hold_merge not validated and not repository-restricted** at `werkrevisor/config.py:175-176`, ORANGE, as a line comment
2. **[medium] Cancel failure fails the check but approval already stands, and a 404 on cancel is not distinguished from a failed network call** at `werkrevisor/cli.py:493-495`, ORANGE, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1364)
3. **[medium] Restart with held merge is not retried when the hold persists and an earlier hold comment exists** at `werkrevisor/cli.py:621-624`, hint, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1369)
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 73120, calls 1, tokens in 72069 / out 824 (reasoning included in out), duration 13.3 s, cost 0.1524 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 3, tokens in 4723, cost 0.0002 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `a66d56e5b063f4fe95c46fe48ebb81e2486a611e` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for a66d56e5b063f4fe95c46fe48ebb81e2486a611e.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `a66d56e5b063f4fe95c46fe48ebb81e2486a611e`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:a66d56e5b063f4fe95c46fe48ebb81e2486a611e -->
[medium] hints_hold_merge not validated and not repository-restricted (werkrevisor)
ORANGE; Jev: real 0.67, severity 2.8 of 3
hints_hold_merge is not in the bool validation loop (only require_wip_transition and automerge are checked), so a non-bool such as the string "false" is truthy and the hold stays on. REPOSITORY_KEYS["gate"] does not exist, so a repository config cannot set it and the README default cannot be changed per repository. Both are consistent with the other gate keys, but the missing type check is a real gap: the string "false" silently keeps the hold on.
**[medium] hints_hold_merge not validated and not repository-restricted** (werkrevisor)
ORANGE; Jev: real 0.67, severity 2.8 of 3
`hints_hold_merge` is not in the bool validation loop (only `require_wip_transition` and `automerge` are checked), so a non-bool such as the string "false" is truthy and the hold stays on. `REPOSITORY_KEYS["gate"]` does not exist, so a repository config cannot set it and the README default cannot be changed per repository. Both are consistent with the other gate keys, but the missing type check is a real gap: the string "false" silently keeps the hold on.
Fixed in 602663a: hints_hold_merge is validated as boolean like the other gate switches; the string "false" is a config error. Test test_the_switch_must_be_a_boolean.
Not changed: like all [gate] keys it is host only, since the host decides how a repository merges.
Fixed in 602663a: `hints_hold_merge` is validated as boolean like the other gate switches; the string "false" is a config error. Test `test_the_switch_must_be_a_boolean`.
Not changed: like all `[gate]` keys it is host only, since the host decides how a repository merges.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:621-624
hint model recommends merge with caution
Findings
[medium] Hold merge can be released when review comments fail to read at werkrevisor/cli.py:520-524, ORANGE, still open in an earlier line comment
[medium] Restart comment is posted on every re-run with open hints at werkrevisor/cli.py:621-624, hint, still open in an earlier line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 74278, calls 1, tokens in 73285 / out 618 (reasoning included in out), duration 11.5 s, cost 0.1527 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3445, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `602663aedc50fe990e6dbc54f5142032f57befaf` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:602663aedc50fe990e6dbc54f5142032f57befaf -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>602663a</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1379">the result for <code>3729f3e</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/cli.py:520-524
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:621-624
- **hint** model recommends merge with caution
### Findings
1. **[medium] Hold merge can be released when review comments fail to read** at `werkrevisor/cli.py:520-524`, ORANGE, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1365)
2. **[medium] Restart comment is posted on every re-run with open hints** at `werkrevisor/cli.py:621-624`, hint, still open in [an earlier line comment](http://git.javagil.de/mi/werkrevisor/pulls/32#issuecomment-1369)
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 74278, calls 1, tokens in 73285 / out 618 (reasoning included in out), duration 11.5 s, cost 0.1527 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3445, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `602663aedc50fe990e6dbc54f5142032f57befaf` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
</details>
YELLOW 1 finding(s) possibly severe, but Jev doubts that they are real: werkrevisor/cli.py:539-548
hint 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
hint 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:633-636
hint model recommends merge with caution
Findings
[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow at werkrevisor/cli.py:539-548, YELLOW, as a line comment
[medium] Held merge on restart is not re-evaluated against the stale result comment at werkrevisor/cli.py:633-636, hint, as a line comment
Classifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 76482, calls 1, tokens in 75481 / out 684 (reasoning included in out), duration 12.5 s, cost 0.1578 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5749, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3534, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).
Reviewed head `3729f3e80751d81403a4ee86c57b482b61fdeab3` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
<!-- werkrevisor:3729f3e80751d81403a4ee86c57b482b61fdeab3 -->
<!-- werkrevisor-verdict:YELLOW -->
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** risky paths changed: werkrevisor/config.py (werkrevisor/config.py), werkrevisor/gitea.py (werkrevisor/gitea.py)
- **YELLOW** 1 finding(s) possibly severe, but Jev doubts that they are real: werkrevisor/cli.py:539-548
- **hint** 1 build change(s) of low risk according to Jev: server/build.gradle.kts (weakens checks 0.02, risk 0.00)
- **hint** 1 finding(s) of low severity or rated minor by Jev: werkrevisor/cli.py:633-636
- **hint** model recommends merge with caution
### Findings
1. **[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow** at `werkrevisor/cli.py:539-548`, YELLOW, as a line comment
2. **[medium] Held merge on restart is not re-evaluated against the stale result comment** at `werkrevisor/cli.py:633-636`, hint, as a line comment
### Classifier
7 of 7 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 76482, calls 1, tokens in 75481 / out 684 (reasoning included in out), duration 12.5 s, cost 0.1578 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5749, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3534, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base 6989c4b).<br>
Reviewed head `3729f3e80751d81403a4ee86c57b482b61fdeab3` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
</sub>
werkrevisor: YELLOW / HUMAN_REVIEW for 3729f3e80751d81403a4ee86c57b482b61fdeab3.
The result comment of werkrevisor holds the details.
werkrevisor: YELLOW / HUMAN_REVIEW for `3729f3e80751d81403a4ee86c57b482b61fdeab3`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:3729f3e80751d81403a4ee86c57b482b61fdeab3 -->
[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow (werkrevisor)
YELLOW; Jev: real 0.52, severity 2.8 of 3
_hold_merge calls cancel_scheduled_merge for any scheduled merge, including one scheduled by an earlier non-GREEN round of the same PR for the human-approval flow. After a new GREEN head with hints, the cancel removes it, which is intended. However, a 404 is treated as success, and any other GiteaError returns exit 10, while a non-GiteaError exception (e.g. a network failure wrapped differently) is not caught in _hold_merge and propagates to execute as publish_failed. That is acceptable, but the approval has already been published, so the state is an approved head with a possibly still-scheduled merge. The exit code is ERROR (30) then; confirm that the failed status check really blocks Gitea's scheduled merge.
**[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow** (werkrevisor)
YELLOW; Jev: real 0.52, severity 2.8 of 3
`_hold_merge` calls `cancel_scheduled_merge` for any scheduled merge, including one scheduled by an earlier non-GREEN round of the same PR for the human-approval flow. After a new GREEN head with hints, the cancel removes it, which is intended. However, a 404 is treated as success, and any other `GiteaError` returns exit 10, while a non-`GiteaError` exception (e.g. a network failure wrapped differently) is not caught in `_hold_merge` and propagates to `execute` as `publish_failed`. That is acceptable, but the approval has already been published, so the state is an approved head with a possibly still-scheduled merge. The exit code is ERROR (30) then; confirm that the failed status check really blocks Gitea's scheduled merge.
Not changed: a network error outside GiteaError ends the run as ERROR (exit code 30), which fails the required status check. Gitea's scheduled merge ("merge when checks succeed") waits until all required checks succeed, so it does not merge the approved head; the branch protection of main requires the context werkator and ai-review/gate.
Not changed: a network error outside `GiteaError` ends the run as ERROR (exit code 30), which fails the required status check. Gitea's scheduled merge ("merge when checks succeed") waits until all required checks succeed, so it does not merge the approved head; the branch protection of main requires the context `werkator` and `ai-review/gate`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
[medium] Held merge on restart is not re-evaluated against the stale result comment (werkrevisor)
hint; Jev: real 0.80, severity 1.8 of 3
When existing is not None and the GREEN review has open hints, _comment_gate posts a new "review restarted ... merge waits" comment on every restart. Only the "merge already scheduled" note is suppressed, so each restart with open hints adds a comment. The test test_a_restart_with_open_hints_comments_that_the_merge_still_waits encodes this behaviour. Repeated restarts will spam the PR. The PR document says only "unless the merge was already scheduled" and does not state this noise.
**[medium] Held merge on restart is not re-evaluated against the stale result comment** (werkrevisor)
hint; Jev: real 0.80, severity 1.8 of 3
When `existing is not None` and the GREEN review has open hints, `_comment_gate` posts a new "review restarted ... merge waits" comment on every restart. Only the "merge already scheduled" note is suppressed, so each restart with open hints adds a comment. The test `test_a_restart_with_open_hints_comments_that_the_merge_still_waits` encodes this behaviour. Repeated restarts will spam the PR. The PR document says only "unless the merge was already scheduled" and does not state this noise.
Not changed, on purpose: a restart is a manual request for the state of the gate, so each restart with open hints answers with a short comment. Werkator restarts a review build only on demand, so this cannot spam a PR by itself.
Not changed, on purpose: a restart is a manual request for the state of the gate, so each restart with open hints answers with a short comment. Werkator restarts a review build only on demand, so this cannot spam a PR by itself.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
YELLOW finding cli.py:539-548 (Jev doubts it): answered in its line comment; the failed gate check blocks a merge that a failed cancel left scheduled.
Hint cli.py:633-636: a comment per manual restart with open hints is intended, answered in its line comment.
YELLOW risky paths werkrevisor/config.py and werkrevisor/gitea.py: by design, the new switch and the cancel call.
Hint server/build.gradle.kts: version bump, judged harmless by Jev.
All earlier line comments are answered in their threads; fixed ones are resolved, the not-changed ones stay open for the human reviewer.
Tests: 504 green; each fix of this PR has a test that fails without it.
Answer to the werkrevisor result for `3729f3e`:
- YELLOW finding `cli.py:539-548` (Jev doubts it): answered in its line comment; the failed gate check blocks a merge that a failed cancel left scheduled.
- Hint `cli.py:633-636`: a comment per manual restart with open hints is intended, answered in its line comment.
- YELLOW risky paths `werkrevisor/config.py` and `werkrevisor/gitea.py`: by design, the new switch and the cancel call.
- Hint `server/build.gradle.kts`: version bump, judged harmless by Jev.
All earlier line comments are answered in their threads; fixed ones are resolved, the not-changed ones stay open for the human reviewer.
Tests: 504 green; each fix of this PR has a test that fails without it.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
See docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md.
🤖 Generated with Claude Code
🟠 werkrevisor ORANGE for
6732eda, superseded by the result for23983b0🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently at
werkrevisor/cli.py:608-611, ORANGE, as a line comment[low] Document omits the cancel-failure and missing-comment behaviour at
docs/prs/2026-10-06-PR#32-hints-hold-the-merge.md:68, hint, as a line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 69656, calls 1, tokens in 68642 / out 536 (reasoning included in out), duration 18.3 s, cost 0.1426 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5632, cost 0.0002 USD, finding judge `jev-1.13.0` calls 1, tokens in 1662, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `6732eda3b4ab70d6fb322ec42021511d9818b3eb` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
werkrevisor: ORANGE / FINDINGS for
6732eda3b4ab70d6fb322ec42021511d9818b3eb.The result comment of werkrevisor holds the details.
@@ -0,0 +65,4 @@- `[gate] hints_hold_merge`, default `true`, applies with `automerge`:at GREEN, werkrevisor counts the unresolved line comments of the bot, from this and earlier rounds.- With open line comments, the bot approves, schedules no merge and cancels a merge scheduled earlier(`DELETE /pulls/{n}/merge`, a 404 means none was scheduled); the gate note goes into the commit status and the result comment.[low] Document omits the cancel-failure and missing-comment behaviour (werkrevisor)
hint
The Solution says the gate note goes into the result comment, but the code writes it into the comment only on the first review of a head (
existing is None). On a restart with open hints the note appears only in the commit status. The document should state this or the code should match it.Fixed in
23983b0: the PR doc says that the gate note, also a failed cancel, goes into the commit status and the result comment, and that a restart posts a short comment.🤖 Generated with Claude Code
@@ -592,3 +607,2 @@result.reasons.append(Reason("self_approval", "the bot cannot approve its own PR", Verdict.ERROR))if publish:_publish(config, pr, gitea, result, existing, bot_login, redactor)created = _publish(config, pr, gitea, result, existing, bot_login, redactor) if publish else {}[medium] Hold counts the bot's own approved-review line comments, but merge cancel fails on non-404 errors silently (werkrevisor)
ORANGE; Jev: real 0.80, severity 3.0 of 3
In the already-reviewed path (
existing is not None),_publishreturns the existing comment anddecision.heldis true, but_note_holdis skipped because ofexisting is None. The result comment then never states the hold on a restart, although the commit status does. Separately,_hold_mergeswallows a failed cancel (non-404) only into the note. For a restart of an unresolved head the note is not in the comment, so a failed cancel stays invisible in the result comment and a merge for the earlier head may still happen.Fixed in
23983b0: a restarted review posts its gate note as a short PR comment, since the result comment names the first review; a failed cancel is part of that note and, sincea66d56e, also fails the gate check (exit code 10).🤖 Generated with Claude Code
🟠 werkrevisor ORANGE for
23983b0, superseded by the result forf11a884🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Hold does not use the hints of the current review when line comments are refused at
werkrevisor/cli.py:491-494, ORANGE, as a line comment[medium] Hold also fires for hints of a restarted review without gate comment on first review at
werkrevisor/cli.py:610-615, hint, still open in an earlier line comment[low] Cancel also runs for a PR that never had a merge scheduled at
werkrevisor/cli.py:518-527, hint, as a line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 71155, calls 1, tokens in 70148 / out 842 (reasoning included in out), duration 14.3 s, cost 0.1487 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5658, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3458, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `23983b00a606a328f481577092e14d1aef19dedd` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
werkrevisor: ORANGE / FINDINGS for
23983b00a606a328f481577092e14d1aef19dedd.The result comment of werkrevisor holds the details.
@@ -488,6 +488,9 @@ def _approval_gate(config, pr, gitea, result, publish, pr_data, bot_login, redacif verdict is Verdict.GREEN:if not publish:return GateDecision(0, "approval not submitted (--no-publish)")hints = _open_bot_line_comments(gitea, pr, bot_login) if config.gate.automerge and config.gate.hints_hold_merge else [][medium] Hold does not use the hints of the current review when line comments are refused (werkrevisor)
ORANGE; Jev: real 0.89, severity 3.0 of 3
_open_bot_line_commentscounts only unresolved bot line comments withposition > 0. If Gitea refused the line comments (line_comments_refused), the findings are carried in the result comment and no line comments exist, so the count is 0 and the merge is scheduled right after the GREEN review. The hold then silently does not apply to the very hints the PR is meant to protect. This is a narrow case (a 400/422 on line comments), but it reproduces the original problem of PR#30.Fixed in
f11a884: findings of this review that are no line comment, e.g. refused by Gitea, count as open hints too; a restart releases them, since it reuses the verdict without findings. Testtest_hints_refused_as_line_comments_hold_the_merge_too, red without the fix.The later finding in this thread, "cancel failure fails the check but the approval stands": intended. The approval stands, but the required gate check fails, and Gitea's "merge when checks succeed" waits for it; a network error outside
GiteaErrorends the run as ERROR, which fails the check too.🤖 Generated with Claude Code
@@ -512,6 +515,18 @@ def _approval_gate(config, pr, gitea, result, publish, pr_data, bot_login, redacreturn GateDecision(0, f"review requested from {', '.join(config.gate.human_reviewers)}" + scheduled)def _hold_merge(pr, gitea, redactor, count):[low] Cancel also runs for a PR that never had a merge scheduled (werkrevisor)
hint
_hold_mergealways sendsDELETE /pulls/{n}/mergeand treats 404 as "none scheduled". This is the documented behavior, but any other error status (e.g. 405 or 409 on some Gitea versions when nothing is scheduled) is reported in the gate note as "could not be cancelled", which can mislead the author when there is nothing to cancel.Not changed in its first form: Gitea 1.27 answers 404 when no merge is scheduled, which counts as success; any other error fails the gate check since
a66d56e, on purpose, since an uncancelled merge would merge the held head.The later finding in this thread, "hold merge can be released when review comments fail to read", was real: fixed in
3729f3e. Unreadable line comments now hold the merge and fail the gate check. Testtest_unreadable_hints_hold_the_merge, red without the fix.🤖 Generated with Claude Code
🟠 werkrevisor ORANGE for
f11a884, superseded by the result fora66d56e🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Reused review reads findings from the wrong state at
werkrevisor/cli.py:518-522, ORANGE, still open in an earlier line comment[medium] Restart comment posted on every GREEN rerun at
werkrevisor/cli.py:619-622, hint, as a line comment[low] Failed cancel gives a misleading note at
werkrevisor/cli.py:525-534, hint, as a line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 72155, calls 1, tokens in 71087 / out 709 (reasoning included in out), duration 12.6 s, cost 0.1493 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5697, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3387, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `f11a8841686e9e44ccdb1b69bec9d26abef9f323` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
werkrevisor: ORANGE / FINDINGS for
f11a8841686e9e44ccdb1b69bec9d26abef9f323.The result comment of werkrevisor holds the details.
@@ -515,0 +522,4 @@return len(_open_bot_line_comments(gitea, pr, bot_login)) + len(in_comment_only)def _hold_merge(pr, gitea, redactor, count):[low] Failed cancel gives a misleading note (werkrevisor)
hint
_hold_mergeonly cancels and returns a note. If the cancel fails with something other than 404, the merge scheduled earlier stays active and will merge the head even though the note says the merge waits. The note does name the failure, but the exit code stays 0 and the status stays green. The operator has to read the note to see that the hold failed.Fixed in
a66d56e: a failed cancel ends the review with exit code 10, so the failed gate check stops the merge scheduled earlier. Testtest_a_failed_cancel_is_named, red without the fix.🤖 Generated with Claude Code
@@ -595,1 +616,4 @@decision = _approval_gate(config, pr, gitea, result, publish, current, bot_login, redactor)if publish and decision.held and existing is None:_note_hold(config, pr, gitea, result, redactor, created, decision.note)elif publish and existing is not None and config.gate.automerge and config.gate.hints_hold_merge \[medium] Restart comment posted on every GREEN rerun (werkrevisor)
hint; Jev: real 0.78, severity 1.3 of 3
The
elifbranch posts a new "review restarted" comment on every rerun of a GREEN head whenautomergeandhints_hold_mergeare on. That includes the case where nothing changed and the merge was already scheduled, so each rerun adds a comment. Posting only when the gate note differs from the previous state, or only for a hold or a first schedule, would avoid the noise.Fixed in
a66d56e: a restart comments only when the merge still waits or is newly scheduled; "merge already scheduled" stays silent. Testtest_a_restart_comments_only_a_change_of_the_merge.The later findings in this thread (a comment on each restart with open hints): intended, see the answer in the thread of 1380.
🤖 Generated with Claude Code
🟠 werkrevisor ORANGE for
a66d56e, superseded by the result for602663a🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] hints_hold_merge not validated and not repository-restricted at
werkrevisor/config.py:175-176, ORANGE, as a line comment[medium] Cancel failure fails the check but approval already stands, and a 404 on cancel is not distinguished from a failed network call at
werkrevisor/cli.py:493-495, ORANGE, still open in an earlier line comment[medium] Restart with held merge is not retried when the hold persists and an earlier hold comment exists at
werkrevisor/cli.py:621-624, hint, still open in an earlier line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 73120, calls 1, tokens in 72069 / out 824 (reasoning included in out), duration 13.3 s, cost 0.1524 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 3, tokens in 4723, cost 0.0002 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `a66d56e5b063f4fe95c46fe48ebb81e2486a611e` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
werkrevisor: ORANGE / FINDINGS for
a66d56e5b063f4fe95c46fe48ebb81e2486a611e.The result comment of werkrevisor holds the details.
@@ -172,6 +172,8 @@ class GateConfig:require_wip_transition: bool = False# The bot schedules the merge for when the checks succeed; after YELLOW or ORANGE a human approval then merges.automerge: bool = False# A GREEN review with unresolved bot line comments approves, but its merge waits until they are resolved.[medium] hints_hold_merge not validated and not repository-restricted (werkrevisor)
ORANGE; Jev: real 0.67, severity 2.8 of 3
hints_hold_mergeis not in the bool validation loop (onlyrequire_wip_transitionandautomergeare checked), so a non-bool such as the string "false" is truthy and the hold stays on.REPOSITORY_KEYS["gate"]does not exist, so a repository config cannot set it and the README default cannot be changed per repository. Both are consistent with the other gate keys, but the missing type check is a real gap: the string "false" silently keeps the hold on.Fixed in
602663a:hints_hold_mergeis validated as boolean like the other gate switches; the string "false" is a config error. Testtest_the_switch_must_be_a_boolean.Not changed: like all
[gate]keys it is host only, since the host decides how a repository merges.🤖 Generated with Claude Code
🟠 werkrevisor ORANGE for
602663a, superseded by the result for3729f3e🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Hold merge can be released when review comments fail to read at
werkrevisor/cli.py:520-524, ORANGE, still open in an earlier line comment[medium] Restart comment is posted on every re-run with open hints at
werkrevisor/cli.py:621-624, hint, still open in an earlier line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 74278, calls 1, tokens in 73285 / out 618 (reasoning included in out), duration 11.5 s, cost 0.1527 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5730, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3445, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `602663aedc50fe990e6dbc54f5142032f57befaf` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Findings
[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow at
werkrevisor/cli.py:539-548, YELLOW, as a line comment[medium] Held merge on restart is not re-evaluated against the stale result comment at
werkrevisor/cli.py:633-636, hint, as a line commentClassifier
7 of 7 units passed all questions (1 PR document(s)).
Usage: model `openrouter/anthropic/claude-sonnet-5.5`, LLM done, tokens counted before the call 76482, calls 1, tokens in 75481 / out 684 (reasoning included in out), duration 12.5 s, cost 0.1578 USD (reported), classifier `jev-1.13.0` calls 7, tokens in 5749, cost 0.0002 USD, finding judge `jev-1.13.0` calls 2, tokens in 3534, cost 0.0001 USD, build file judge `jev-1.13.0` calls 1, tokens in 560, cost 0.0000 USD, config: defaults + host + repository (.werkrevisor.toml at base6989c4b).Reviewed head `3729f3e80751d81403a4ee86c57b482b61fdeab3` against base `6989c4b7dd63946e0f33fcd6b1e0a64764735798`, werkrevisor 0.20.0.
werkrevisor: YELLOW / HUMAN_REVIEW for
3729f3e80751d81403a4ee86c57b482b61fdeab3.The result comment of werkrevisor holds the details.
@@ -515,0 +536,4 @@return len(_open_bot_line_comments(gitea, pr, bot_login, strict=True)) + len(in_comment_only)def _hold_merge(pr, gitea, redactor, count):[medium] Cancel can drop a human-requested merge on YELLOW/ORANGE-approved flow (werkrevisor)
YELLOW; Jev: real 0.52, severity 2.8 of 3
_hold_mergecallscancel_scheduled_mergefor any scheduled merge, including one scheduled by an earlier non-GREEN round of the same PR for the human-approval flow. After a new GREEN head with hints, the cancel removes it, which is intended. However, a 404 is treated as success, and any otherGiteaErrorreturns exit 10, while a non-GiteaErrorexception (e.g. a network failure wrapped differently) is not caught in_hold_mergeand propagates toexecuteaspublish_failed. That is acceptable, but the approval has already been published, so the state is an approved head with a possibly still-scheduled merge. The exit code is ERROR (30) then; confirm that the failed status check really blocks Gitea's scheduled merge.Not changed: a network error outside
GiteaErrorends the run as ERROR (exit code 30), which fails the required status check. Gitea's scheduled merge ("merge when checks succeed") waits until all required checks succeed, so it does not merge the approved head; the branch protection of main requires the contextwerkatorandai-review/gate.🤖 Generated with Claude Code
@@ -595,1 +630,4 @@decision = _approval_gate(config, pr, gitea, result, publish, current, bot_login, redactor)if publish and decision.held and existing is None:_note_hold(config, pr, gitea, result, redactor, created, decision.note)elif publish and existing is not None and config.gate.automerge and config.gate.hints_hold_merge \[medium] Held merge on restart is not re-evaluated against the stale result comment (werkrevisor)
hint; Jev: real 0.80, severity 1.8 of 3
When
existing is not Noneand the GREEN review has open hints,_comment_gateposts a new "review restarted ... merge waits" comment on every restart. Only the "merge already scheduled" note is suppressed, so each restart with open hints adds a comment. The testtest_a_restart_with_open_hints_comments_that_the_merge_still_waitsencodes this behaviour. Repeated restarts will spam the PR. The PR document says only "unless the merge was already scheduled" and does not state this noise.Not changed, on purpose: a restart is a manual request for the state of the gate, so each restart with open hints answers with a short comment. Werkator restarts a review build only on demand, so this cannot spam a PR by itself.
🤖 Generated with Claude Code
Answer to the werkrevisor result for
3729f3e:cli.py:539-548(Jev doubts it): answered in its line comment; the failed gate check blocks a merge that a failed cancel left scheduled.cli.py:633-636: a comment per manual restart with open hints is intended, answered in its line comment.werkrevisor/config.pyandwerkrevisor/gitea.py: by design, the new switch and the cancel call.server/build.gradle.kts: version bump, judged harmless by Jev.All earlier line comments are answered in their threads; fixed ones are resolved, the not-changed ones stay open for the human reviewer.
Tests: 504 green; each fix of this PR has a test that fails without it.
🤖 Generated with Claude Code
ai-reviewer referenced this pull request2026-10-07 10:36:22 +02:00