- The reason of `--checked` moves from the top of the comment to a closing section "Assessment of the findings" after the report.
- A second `--attach` for the same commit replaces the own report; a report of a new commit folds the earlier ones.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-code
changed title from WIP: werkrevisor 0.65.3: draft-review --attach --checked puts the assessment of the findings after the report to WIP: werkrevisor 0.66.0: draft-review --attach puts the assessment after the report and replaces the report of the same commit2026-10-23 15:05:39 +02:00
claude-code
marked the pull request as ready for review 2026-10-23 15:07:02 +02:00
Gate: approved by werkrevisor; merge waits for 2 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit.
Change kind: mixed.
Reasons
hint writing rules violated in the changed docs: docs/prs/2026-10-23-PR#139-assessment-after-report.md:93: line longer than 128 characters (130)
hint 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
hint the PR document may contradict the file according to Jev: werkrevisor/draftreview.py:181
hint the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file)
Findings
[medium] Claimed implementation is missing in the file at werkrevisor/draftreview.py:181, hint, as a line comment
Classifier
8 of 8 units passed all questions (1 PR document(s)).
2 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40917, duration 724.6 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6742, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26040, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.3 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 722.7 s, config: defaults + host + repository (.werkrevisor.toml at main 284f80e).
Reviewed head `6afb1dd3ac9f78ecdc749f33518101f066dd191d` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
<!-- werkrevisor:6afb1dd3ac9f78ecdc749f33518101f066dd191d -->
<!-- werkrevisor-verdict:GREEN -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,ff8254d7899d9edf65e5d8b8d0bbd2b9,584d401a3ec5c1ef07debe2073a1b4ca,2dfcef3ce4f9e2b999b78c03cf87b6ac,0c3ab7b727a91fd7b60ded1a482d27a8,3b2fb0ad5630f9e0ff42102e8d814bbd,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,02d4d56e016309b8d5cdfe5777db22c6,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,11a77d4f05143d222a7b64da99ba8466,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,fc5b8f2608593a5b1f9c1c4de4daf2c5,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,e8a1c7f5ce26e1492c409a9ce32a1620,2aecc34410397bfb48945f3ca0cb8332,6cbd03db48a7ef2fb65064c248ac2d5a,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor-held-by-line-comments -->
<!-- werkrevisor-folded -->
<details><summary>🟢 werkrevisor GREEN for <code>6afb1dd</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7377">the result for <code>020d14e</code></a></summary>
## 🟢 werkrevisor: GREEN / PASS
Gate: approved by werkrevisor; merge waits for 2 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit.
Change kind: `mixed`.
### Reasons
- **hint** writing rules violated in the changed docs: docs/prs/2026-10-23-PR#139-assessment-after-report.md:93: line longer than 128 characters (130)
- **hint** 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
- **hint** the PR document may contradict the file according to Jev: werkrevisor/draftreview.py:181
- **hint** the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file)
### Findings
1. **[medium] Claimed implementation is missing in the file** at `werkrevisor/draftreview.py:181`, hint, as a line comment
### Classifier
8 of 8 units passed all questions (1 PR document(s)).
2 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40917, duration 724.6 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6742, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26040, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.3 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 722.7 s, config: defaults + host + repository (.werkrevisor.toml at main 284f80e).<br>
Reviewed head `6afb1dd3ac9f78ecdc749f33518101f066dd191d` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
</sub>
</details>
werkrevisor: GREEN / PASS for 6afb1dd3ac9f78ecdc749f33518101f066dd191d.
The result comment of werkrevisor holds the details.
werkrevisor: GREEN / PASS for `6afb1dd3ac9f78ecdc749f33518101f066dd191d`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:6afb1dd3ac9f78ecdc749f33518101f066dd191d -->
[medium] Claimed implementation is missing in the file (werkrevisor)
hint
Jev compared the diff of this file with the PR document: Claimed implementation is missing in the file 0.82.
Fix the PR document or the code, or reply why the file belongs to the PR, and resolve this comment.
File fingerprint f7e6d41bb0ff.
**[medium] Claimed implementation is missing in the file** (werkrevisor)
hint
Jev compared the diff of this file with the PR document: Claimed implementation is missing in the file 0.82.
Fix the PR document or the code, or reply why the file belongs to the PR, and resolve this comment.
File fingerprint `f7e6d41bb0ff`.
Gate: approved by werkrevisor; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind: mixed.
Reasons
hint approval of werkrevisor for 6afb1dd not carried over: 1 approved block(s) are missing
hint 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
hint 9 changed file(s) agree with the PR document according to Jev
hint the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file)
Classifier
8 of 8 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40633, duration 725.3 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6791, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26481, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.5 s, model_review 722.9 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).
Reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
<!-- werkrevisor:020d14eff64b7c49a6347dc00275cf883ca7f8ec -->
<!-- werkrevisor-verdict:GREEN -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,4b15c41ee41a54f5c5b706747ed422df,584d401a3ec5c1ef07debe2073a1b4ca,2dfcef3ce4f9e2b999b78c03cf87b6ac,0c3ab7b727a91fd7b60ded1a482d27a8,3b2fb0ad5630f9e0ff42102e8d814bbd,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,02d4d56e016309b8d5cdfe5777db22c6,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,11a77d4f05143d222a7b64da99ba8466,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,fc5b8f2608593a5b1f9c1c4de4daf2c5,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,e8a1c7f5ce26e1492c409a9ce32a1620,2aecc34410397bfb48945f3ca0cb8332,6cbd03db48a7ef2fb65064c248ac2d5a,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor-folded -->
<details><summary>🟢 werkrevisor GREEN for <code>020d14e</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7395">the result for <code>ff0dd74</code></a></summary>
## 🟢 werkrevisor: GREEN / PASS
Gate: approved by werkrevisor; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind: `mixed`.
### Reasons
- **hint** approval of werkrevisor for `6afb1dd` not carried over: 1 approved block(s) are missing
- **hint** 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
- **hint** 9 changed file(s) agree with the PR document according to Jev
- **hint** the model review failed: TimeoutError: review exceeded 720 seconds (advisory: Jev judged every changed file)
### Classifier
8 of 8 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40633, duration 725.3 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6791, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26481, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.5 s, model_review 722.9 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).<br>
Reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
</sub>
</details>
werkrevisor: GREEN / PASS for 020d14eff64b7c49a6347dc00275cf883ca7f8ec.
The result comment of werkrevisor holds the details.
werkrevisor: GREEN / PASS for `020d14eff64b7c49a6347dc00275cf883ca7f8ec`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:020d14eff64b7c49a6347dc00275cf883ca7f8ec -->
[medium] Replacing a previously folded report skips folding the superseded report (Codex review)
After attaching reports for commits A and B, reset the PR head to A and attach again. The replacement unfolds A, but this early return skips the folding loop, leaving B unfolded too. Reproduced with FakeGitea: both reports remain open, contrary to the promised single current report. Fold the other reports after replacement as well.
Fix it, or reply why it does not hold, and resolve this comment.
**[medium] Replacing a previously folded report skips folding the superseded report** (Codex review)
After attaching reports for commits A and B, reset the PR head to A and attach again. The replacement unfolds A, but this early return skips the folding loop, leaving B unfolded too. Reproduced with FakeGitea: both reports remain open, contrary to the promised single current report. Fold the other reports after replacement as well.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in ff0dd74: a replacement folds the reports of the other heads too; test_a_replaced_report_folds_the_reports_of_other_heads failed before the fix.
Fixed in `ff0dd74`: a replacement folds the reports of the other heads too; `test_a_replaced_report_folds_the_reports_of_other_heads` failed before the fix.
The change permanently deletes existing Gitea comment attachments when replacing a report. A mistake in selecting those attachments could irreversibly destroy stored review artifacts.
Findings
[medium] Replacing a previously folded report skips folding the superseded report at werkrevisor/reviewreport.py:178, as a line comment
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 265620 (cached 232960) / out 2382, 101.2 s, 12 commands; reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec`.
<!-- werkrevisor-codex:020d14eff64b7c49a6347dc00275cf883ca7f8ec -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change permanently deletes existing Gitea comment attachments when replacing a report. A mistake in selecting those attachments could irreversibly destroy stored review artifacts.
### Findings
1. **[medium] Replacing a previously folded report skips folding the superseded report** at `werkrevisor/reviewreport.py:178`, as a line comment
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 265620 (cached 232960) / out 2382, 101.2 s, 12 commands; reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec`.
</sub>
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
ORANGE 1 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:172-175
hint approval of werkrevisor for 020d14e not carried over: 7 approved block(s) are missing
hint 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
hint 9 changed file(s) agree with the PR document according to Jev
hint 1 finding(s) of low severity or rated minor by Jev: tests/fakes.py:193-195
hint model recommends changes before merge
Findings
[medium] Edit Failure at werkrevisor/reviewreport.py:172-175, ORANGE, as a line comment
[medium] Asset IDs at tests/fakes.py:193-195, hint, as a line comment
Classifier
8 of 8 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 41431, calls 1, tokens in 39971 / out 47409 (reasoning included in out), duration 324.6 s, cost 0.0689 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6814, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3359, cost 0.0001 USD, PR document check `jev-1.14.0` calls 9, tokens in 27370, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 8240, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 322.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).
Reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
<!-- werkrevisor:ff0dd748d8b3002c896e6222b7ac3b5c0173099b -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,9b400628fb89ba4f90664b1a5c483c07,584d401a3ec5c1ef07debe2073a1b4ca,43b7f8e0ef69521bf71c54e69f6c3ff4,0c3ab7b727a91fd7b60ded1a482d27a8,3b2fb0ad5630f9e0ff42102e8d814bbd,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,7793562fb68cb2a6d58357819d1ed823,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,e0feb582c70b361f3da4881d4a86e74d,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,fc5b8f2608593a5b1f9c1c4de4daf2c5,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,36e9f85e1bd83c15e865964448e9d610,a5a104386fe189ae2672a0bc65fc3090,3ec169e5e9e5a14a70a0c11044bfa50c,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor:diagrams -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>ff0dd74</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7412">the result for <code>77bb9d9</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:172-175
- **hint** approval of werkrevisor for `020d14e` not carried over: 7 approved block(s) are missing
- **hint** 6 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
- **hint** 9 changed file(s) agree with the PR document according to Jev
- **hint** 1 finding(s) of low severity or rated minor by Jev: tests/fakes.py:193-195
- **hint** model recommends changes before merge
### Findings
1. **[medium] Edit Failure** at `werkrevisor/reviewreport.py:172-175`, ORANGE, as a line comment
2. **[medium] Asset IDs** at `tests/fakes.py:193-195`, hint, as a line comment
### Classifier
8 of 8 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 41431, calls 1, tokens in 39971 / out 47409 (reasoning included in out), duration 324.6 s, cost 0.0689 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6814, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3359, cost 0.0001 USD, PR document check `jev-1.14.0` calls 9, tokens in 27370, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 8240, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 322.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).<br>
Reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
</sub>
### Diagrams
Drawn by a model from the diff with [PR Lens](https://github.com/coldteadotai/pr-lens): a view of what the PR touches, not a statement of what it does.


</details>
werkrevisor: ORANGE / FINDINGS for ff0dd748d8b3002c896e6222b7ac3b5c0173099b.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `ff0dd748d8b3002c896e6222b7ac3b5c0173099b`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:ff0dd748d8b3002c896e6222b7ac3b5c0173099b -->
The asset ID is derived from the current asset count, so it is reused after deletions. After two replacements of the same comment, deleting the old asset can also delete the newly uploaded one because both have the same ID. The URL also omits the asset identity, so the test cannot prove that the body links the new attachment. Use a monotonic ID or UUID and include it in the fake URL.
**[medium] Asset IDs** (werkrevisor)
hint; Jev: real 0.76, severity 2.1 of 3
The asset ID is derived from the current asset count, so it is reused after deletions. After two replacements of the same comment, deleting the old asset can also delete the newly uploaded one because both have the same ID. The URL also omits the asset identity, so the test cannot prove that the body links the new attachment. Use a monotonic ID or UUID and include it in the fake URL.
Fixed in 4578286: the fake counts asset IDs up and puts the ID into the URL, as Gitea never reuses them; the replacement test now replaces twice and checks the URL of the new asset.
Fixed in `4578286`: the fake counts asset IDs up and puts the ID into the URL, as Gitea never reuses them; the replacement test now replaces twice and checks the URL of the new asset.
The exception path assumes a failed comment edit means the comment was not changed. If Gitea applies the edit but its response is lost, the live comment references the newly uploaded assets and this cleanup deletes them, leaving broken SVGs. Keep the new assets until the resulting comment has been verified, or otherwise make the replacement retry-safe.
**[medium] Edit Failure** (werkrevisor)
ORANGE; Jev: real 0.80, severity 3.0 of 3
The exception path assumes a failed comment edit means the comment was not changed. If Gitea applies the edit but its response is lost, the live comment references the newly uploaded assets and this cleanup deletes them, leaving broken SVGs. Keep the new assets until the resulting comment has been verified, or otherwise make the replacement retry-safe.
Fixed in 4578286: after a failed edit, attach reads the comment again and deletes only the new SVGs that it does not link; if the read fails too, it keeps them. The old SVGs go only if the new body does not link them. test_an_edit_applied_despite_a_lost_response_keeps_its_svgs failed before the fix.
Fixed in `4578286`: after a failed edit, `attach` reads the comment again and deletes only the new SVGs that it does not link; if the read fails too, it keeps them. The old SVGs go only if the new body does not link them. `test_an_edit_applied_despite_a_lost_response_keeps_its_svgs` failed before the fix.
claude-code marked this conversation as resolved
ai-reviewer
scheduled this pull request to auto merge when all checks succeed 2026-10-23 16:22:40 +02:00
ai-reviewer
requested review from mi 2026-10-23 16:22:40 +02:00
old contains every attachment returned by list_comment_assets, and this call deletes all of them. If a user added supporting logs or screenshots to the report comment, repeating --attach permanently deletes those files along with the generated SVGs. An in-memory reproduction confirms this. Cleanup must restrict deletion to the generated attachments being replaced.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Replacement deletes unrelated attachments** (Codex review)
`old` contains every attachment returned by `list_comment_assets`, and this call deletes all of them. If a user added supporting logs or screenshots to the report comment, repeating `--attach` permanently deletes those files along with the generated SVGs. An in-memory reproduction confirms this. Cleanup must restrict deletion to the generated attachments being replaced.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in 77bb9d9: a replacement deletes only the SVGs of PR Lens that the old report linked and the new one does not; a file that someone added to the comment stays. test_a_replacement_keeps_a_file_added_by_hand failed before the fix.
Fixed in `77bb9d9`: a replacement deletes only the SVGs of PR Lens that the old report linked and the new one does not; a file that someone added to the comment stays. `test_a_replacement_keeps_a_file_added_by_hand` failed before the fix.
The change introduces irreversible deletion of existing comment attachments. Incorrect cleanup can destroy manually added evidence, which the current tests do not cover.
Findings
[high] Replacement deletes unrelated attachments at werkrevisor/reviewreport.py:177, as a line comment
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 292601 (cached 252672) / out 2182, 113.4 s, 12 commands; reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b`.
<!-- werkrevisor-codex:ff0dd748d8b3002c896e6222b7ac3b5c0173099b -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change introduces irreversible deletion of existing comment attachments. Incorrect cleanup can destroy manually added evidence, which the current tests do not cover.
### Findings
1. **[high] Replacement deletes unrelated attachments** at `werkrevisor/reviewreport.py:177`, as a line comment
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 292601 (cached 252672) / out 2182, 113.4 s, 12 commands; reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b`.
</sub>
werkrevisor: a lost response of the edit deleted SVGs that the comment links.
The fake never reuses asset IDs, as Gitea.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
hint 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
hint 10 changed file(s) agree with the PR document according to Jev
hint 2 finding(s) of low severity or rated minor by Jev: werkrevisor/reviewreport.py:83-85, docs/prs/2026-10-23-PR#139-assessment-after-report.md:25
hint model recommends changes before merge
Findings
[medium] Attachment limit at werkrevisor/reviewreport.py:173-189, ORANGE, as a line comment
[medium] Blank lines at werkrevisor/reviewreport.py:83-85, hint, as a line comment
[low] Earlier-report wording at docs/prs/2026-10-23-PR#139-assessment-after-report.md:25
hint
The Non-Goals states categorically that the report of an earlier commit is not replaced, but the implemented rollback path replaces exactly that report when its commit becomes the current head. Clarify that the non-replacement rule applies only while another head is current, so the documented contract does not contradict the tested behavior.
7 of 8 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 48753, calls 1, tokens in 47045 / out 22015 (reasoning included in out), duration 392.3 s, cost 0.0405 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6894, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3740, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 32031, cost 0.0013 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.4 s, doc_check 0.5 s, context 0.3 s, model_review 389.9 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).
Reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
<!-- werkrevisor:77bb9d936112c5bcf4eb5956def14657b2b0ff36 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,8f487e1469c0c2331a4fe1c34548c26c,584d401a3ec5c1ef07debe2073a1b4ca,43b7f8e0ef69521bf71c54e69f6c3ff4,e5915cacb826cfadfda160f27d7e8b25,3b2fb0ad5630f9e0ff42102e8d814bbd,d766d34c2b5ca945849a3eedaf3b8ee2,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,c2f5d61fcb315696ef3344ad34ed5eb2,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,e0feb582c70b361f3da4881d4a86e74d,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,c27d53f3c15d57c0e65913ba8e447819,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,33e56c6fbaaf0cbc04099d2d97019623,a5a104386fe189ae2672a0bc65fc3090,d3c7da7d24698c325520c57b15483bd8,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor:diagrams -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>77bb9d9</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7420">the result for <code>79591ad</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:173-189
- **YELLOW** spec: docs/prs/2026-10-23-PR#139-assessment-after-report.md Scenario#139.02 more_than_one_aspect (0.62 > yellow_above = 0.6)
- **hint** 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.03, risk 0.00, security 0.02)
- **hint** 10 changed file(s) agree with the PR document according to Jev
- **hint** 2 finding(s) of low severity or rated minor by Jev: werkrevisor/reviewreport.py:83-85, docs/prs/2026-10-23-PR#139-assessment-after-report.md:25
- **hint** model recommends changes before merge
### Findings
1. **[medium] Attachment limit** at `werkrevisor/reviewreport.py:173-189`, ORANGE, as a line comment
2. **[medium] Blank lines** at `werkrevisor/reviewreport.py:83-85`, hint, as a line comment
3. **[low] Earlier-report wording** at `docs/prs/2026-10-23-PR#139-assessment-after-report.md:25`
hint
The Non-Goals states categorically that the report of an earlier commit is not replaced, but the implemented rollback path replaces exactly that report when its commit becomes the current head. Clarify that the non-replacement rule applies only while another head is current, so the documented contract does not contradict the tested behavior.
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-23-PR#139-assessment-after-report.md Scenario#139.02 | more_than_one_aspect | 0.62 | – | YELLOW |
7 of 8 units passed all questions (1 PR document(s)).
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 48753, calls 1, tokens in 47045 / out 22015 (reasoning included in out), duration 392.3 s, cost 0.0405 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6894, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3740, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 32031, cost 0.0013 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.4 s, doc_check 0.5 s, context 0.3 s, model_review 389.9 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).<br>
Reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
</sub>
### Diagrams
Drawn by a model from the diff with [PR Lens](https://github.com/coldteadotai/pr-lens): a view of what the PR touches, not a statement of what it does.


</details>
werkrevisor: ORANGE / FINDINGS for 77bb9d936112c5bcf4eb5956def14657b2b0ff36.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `77bb9d936112c5bcf4eb5956def14657b2b0ff36`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:77bb9d936112c5bcf4eb5956def14657b2b0ff36 -->
Removing the draft line leaves both neighboring empty lines in the header. The cleanup checks the previous line of the original list rather than the already-filtered list, so confirm() emits three consecutive newlines before the first report section. This adds an unintended blank line to every checked report and makes test_a_reason_follows_the_report_as_assessment fail its assertNotIn("\\n\\n\\n", body) check. Collapse the blank lines using the previously retained element or remove the blank adjacent to the deleted draft line.
**[medium] Blank lines** (werkrevisor)
hint; Jev: real 0.82, severity 1.6 of 3
Removing the draft line leaves both neighboring empty lines in the header. The cleanup checks the previous line of the original list rather than the already-filtered list, so `confirm()` emits three consecutive newlines before the first report section. This adds an unintended blank line to every checked report and makes `test_a_reason_follows_the_report_as_assessment` fail its `assertNotIn("\\n\\n\\n", body)` check. Collapse the blank lines using the previously retained element or remove the blank adjacent to the deleted draft line.
Does not hold: the comprehension in line 82 reads header after the draft line is filtered out in line 81, so header[i - 1] is the previous retained line and the blank line after the removed draft line goes. test_a_reason_follows_the_report_as_assessment asserts no \n\n\n and passes in the pinned PR-Agent image (910 tests OK at 79591ad). No change.
Does not hold: the comprehension in line 82 reads `header` after the draft line is filtered out in line 81, so `header[i - 1]` is the previous retained line and the blank line after the removed draft line goes. `test_a_reason_follows_the_report_as_assessment` asserts no `\n\n\n` and passes in the pinned PR-Agent image (910 tests OK at `79591ad`). No change.
A replacement uploads all new SVG assets before deleting the old generated assets, so the comment temporarily contains both sets. If the old report is already at Gitea's per-comment attachment limit, the new upload is rejected and the same-head replacement cannot proceed. This affects reports with several diagrams and is not exposed by the unlimited fake. Avoid the temporary over-limit state, such as by reusing suitable existing assets or providing a safe fallback.
**[medium] Attachment limit** (werkrevisor)
ORANGE; Jev: real 0.79, severity 2.9 of 3
A replacement uploads all new SVG assets before deleting the old generated assets, so the comment temporarily contains both sets. If the old report is already at Gitea's per-comment attachment limit, the new upload is rejected and the same-head replacement cannot proceed. This affects reports with several diagrams and is not exposed by the unlimited fake. Avoid the temporary over-limit state, such as by reusing suitable existing assets or providing a safe fallback.
No change: a rejected upload is already the safe fallback. _upload deletes the SVGs it uploaded, the comment keeps its old body and old SVGs, and --attach exits with the error (test_a_failed_replacement_keeps_the_report_and_its_svgs). Gitea's [attachment] MAX_FILES limits one upload form; to my knowledge the API for comment assets counts no attachments per comment. A draft has a few PR Lens diagrams, so old and new together stay small. Left for the human to judge.
No change: a rejected upload is already the safe fallback. `_upload` deletes the SVGs it uploaded, the comment keeps its old body and old SVGs, and `--attach` exits with the error (`test_a_failed_replacement_keeps_the_report_and_its_svgs`). Gitea's `[attachment] MAX_FILES` limits one upload form; to my knowledge the API for comment assets counts no attachments per comment. A draft has a few PR Lens diagrams, so old and new together stay small. Left for the human to judge.
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
The change overwrites existing review comments and permanently deletes their previous SVG attachments. This introduces irreversible changes to existing review data, requiring human review under the stated criteria.
No findings.
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 360336 (cached 315776) / out 2745, 135.5 s, 18 commands; reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36`.
<!-- werkrevisor-codex:77bb9d936112c5bcf4eb5956def14657b2b0ff36 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change overwrites existing review comments and permanently deletes their previous SVG attachments. This introduces irreversible changes to existing review data, requiring human review under the stated criteria.
No findings.
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 360336 (cached 315776) / out 2745, 135.5 s, 18 commands; reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36`.
</sub>
ORANGE 2 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:186-189, werkrevisor/reviewreport.py:167-210
hint 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
hint 10 changed file(s) agree with the PR document according to Jev
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-23-PR#139-assessment-after-report.md:62-73
hint model recommends changes before merge
hint model rates the risk as high (advisory: Jev judged every changed file)
Findings
[high] Asset Deletion at werkrevisor/reviewreport.py:186-189, ORANGE, as a line comment
[medium] Stale Body at werkrevisor/reviewreport.py:167-210, ORANGE, as a line comment
[low] Ambiguous Failure at docs/prs/2026-10-23-PR#139-assessment-after-report.md:62-73, hint, as a line comment
Classifier
10 of 10 units passed all questions (1 PR document(s)).
3 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 49061, calls 1, tokens in 47331 / out 43261 (reasoning included in out), duration 656.3 s, cost 0.0661 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8705, cost 0.0004 USD, finding judge `jev-1.14.0` calls 2, tokens in 4284, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 33741, cost 0.0014 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.4 s, model_review 653.5 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).
Reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
<!-- werkrevisor:79591ad69bd5ca48d99106774c6c3523f8625f13 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,f6723408229ee59097f3414b48be2f29,584d401a3ec5c1ef07debe2073a1b4ca,43b7f8e0ef69521bf71c54e69f6c3ff4,e5915cacb826cfadfda160f27d7e8b25,3b2fb0ad5630f9e0ff42102e8d814bbd,d766d34c2b5ca945849a3eedaf3b8ee2,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,e61f13b9d25457471e650c0a9eee7bd5,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,e0feb582c70b361f3da4881d4a86e74d,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,c27d53f3c15d57c0e65913ba8e447819,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,33e56c6fbaaf0cbc04099d2d97019623,a5a104386fe189ae2672a0bc65fc3090,d3c7da7d24698c325520c57b15483bd8,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor:diagrams -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>79591ad</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7430">the result for <code>fe7a622</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 2 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:186-189, werkrevisor/reviewreport.py:167-210
- **hint** 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
- **hint** 10 changed file(s) agree with the PR document according to Jev
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-23-PR#139-assessment-after-report.md:62-73
- **hint** model recommends changes before merge
- **hint** model rates the risk as high (advisory: Jev judged every changed file)
### Findings
1. **[high] Asset Deletion** at `werkrevisor/reviewreport.py:186-189`, ORANGE, as a line comment
2. **[medium] Stale Body** at `werkrevisor/reviewreport.py:167-210`, ORANGE, as a line comment
3. **[low] Ambiguous Failure** at `docs/prs/2026-10-23-PR#139-assessment-after-report.md:62-73`, hint, as a line comment
### Classifier
10 of 10 units passed all questions (1 PR document(s)).
3 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 49061, calls 1, tokens in 47331 / out 43261 (reasoning included in out), duration 656.3 s, cost 0.0661 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8705, cost 0.0004 USD, finding judge `jev-1.14.0` calls 2, tokens in 4284, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 33741, cost 0.0014 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.4 s, model_review 653.5 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).<br>
Reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
</sub>
### Diagrams
Drawn by a model from the diff with [PR Lens](https://github.com/coldteadotai/pr-lens): a view of what the PR touches, not a statement of what it does.


</details>
werkrevisor: ORANGE / FINDINGS for 79591ad69bd5ca48d99106774c6c3523f8625f13.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `79591ad69bd5ca48d99106774c6c3523f8625f13`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:79591ad69bd5ca48d99106774c6c3523f8625f13 -->
The scenario heading promises that a failed replacement leaves the old report, but the implementation also reports failure when the edit was applied and only its response was lost; the referenced lost-response test shows that the new report then remains. The Given/When/Then only states that links reference attached SVGs and never identifies which report survives. Split the rejected edit and unknown-response outcomes so the documented contract is unambiguous.
**[low] Ambiguous Failure** (werkrevisor)
hint
The scenario heading promises that a failed replacement leaves the old report, but the implementation also reports failure when the edit was applied and only its response was lost; the referenced lost-response test shows that the new report then remains. The Given/When/Then only states that links reference attached SVGs and never identifies which report survives. Split the rejected edit and unknown-response outcomes so the documented contract is unambiguous.
Fixed in fe7a622: Scenario#139.03 is now "a failed replacement leaves no broken links": the comment holds the old or the new report, and each SVG that it links is attached; the When names both failures.
Fixed in `fe7a622`: Scenario#139.03 is now "a failed replacement leaves no broken links": the comment holds the old or the new report, and each SVG that it links is attached; the When names both failures.
reports captures each earlier comment body before the asset uploads and edits, but fold later writes that stale snapshot back with a full-body PATCH. If an earlier report is edited while attachments are being uploaded, that edit is silently discarded. Re-read and preserve the current body before folding it.
**[medium] Stale Body** (werkrevisor)
ORANGE; Jev: real 0.83, severity 3.0 of 3
`reports` captures each earlier comment body before the asset uploads and edits, but `fold` later writes that stale snapshot back with a full-body PATCH. If an earlier report is edited while attachments are being uploaded, that edit is silently discarded. Re-read and preserve the current body before folding it.
Fixed in fe7a622: attach reads each earlier report again right before it folds it. test_a_fold_keeps_an_edit_made_meanwhile failed before the fix.
Fixed in `fe7a622`: `attach` reads each earlier report again right before it folds it. `test_a_fold_keeps_an_edit_made_meanwhile` failed before the fix.
The cleanup treats every old attachment whose name starts with pr-lens- and whose URL occurs in the old body as tool-generated. A user-added pr-lens-custom.svg that was linked in that body is therefore deleted during replacement, contradicting the promise that files added by hand remain. Track the asset IDs uploaded by attach instead of inferring ownership from the filename and link.
**[high] Asset Deletion** (werkrevisor)
ORANGE; Jev: real 0.84, severity 3.0 of 3
The cleanup treats every old attachment whose name starts with `pr-lens-` and whose URL occurs in the old body as tool-generated. A user-added `pr-lens-custom.svg` that was linked in that body is therefore deleted during replacement, contradicting the promise that files added by hand remain. Track the asset IDs uploaded by `attach` instead of inferring ownership from the filename and link.
Fixed in fe7a622: the comment names the IDs of the SVGs that attach uploaded in <!-- hs-review-assets:<ids> -->; a replacement deletes only those. test_a_replacement_keeps_an_svg_linked_by_hand failed before the fix.
Fixed in `fe7a622`: the comment names the IDs of the SVGs that `attach` uploaded in `<!-- hs-review-assets:<ids> -->`; a replacement deletes only those. `test_a_replacement_keeps_an_svg_linked_by_hand` failed before the fix.
The change overwrites existing review comments and permanently deletes their previous diagram attachments. This introduces irreversible changes to existing data, so human review is required.
No findings.
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 313750 (cached 274944) / out 2457, 113.1 s, 7 commands; reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13`.
<!-- werkrevisor-codex:79591ad69bd5ca48d99106774c6c3523f8625f13 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change overwrites existing review comments and permanently deletes their previous diagram attachments. This introduces irreversible changes to existing data, so human review is required.
No findings.
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 313750 (cached 274944) / out 2457, 113.1 s, 7 commands; reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13`.
</sub>
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
werkrevisor: an SVG of PR Lens that someone linked by hand was deleted;
a fold wrote back the body from before the uploads.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ORANGE 2 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:182-184, README.md:1641-1643
hint writing rules violated in the changed docs: docs/prs/2026-10-23-PR#139-assessment-after-report.md:109: paragraph with 7 sentences, more than 5
hint 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
hint 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
hint 10 changed file(s) agree with the PR document according to Jev
hint 1 finding(s) of low severity or rated minor by Jev: docs/werkrevisor.werkbaum:209-212
hint model recommends changes before merge
hint model rates the risk as high (advisory: Jev judged every changed file)
Findings
[high] Content Loss at werkrevisor/reviewreport.py:182-184, ORANGE, as a line comment
[medium] Fold Mismatch at README.md:1641-1643, ORANGE, as a line comment
[medium] Diagram Omission at docs/werkrevisor.werkbaum:209-212
hint; Jev: real 0.84, severity 1.9 of 3
AGENTS.md requires a PR that changes review steps or decisions to update the diagrams under docs/. This PR changes the attachment and replacement workflow and marks the diagrams.assessment and diagrams.replace items as completed, but the diff contains no diagram update. The required diagram changes for the new assessment position and same-commit replacement flow are missing.
Classifier
10 of 10 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 50218, calls 1, tokens in 48464 / out 43296 (reasoning included in out), duration 645.9 s, cost 0.0665 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8768, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 5938, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 35383, cost 0.0015 USD, build file judge `jev-1.14.0` calls 8, tokens in 9944, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.3 s, model_review 643.2 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).
Reviewed head `fe7a622e4969eb3f487357848240b61434a78480` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
<!-- werkrevisor:fe7a622e4969eb3f487357848240b61434a78480 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:c95e396b651ea742edc3e0b17c1f2b37,498e53ca4875d0729c38b68a70236909,800eb703ea0baf48082797d29206970c,584d401a3ec5c1ef07debe2073a1b4ca,43b7f8e0ef69521bf71c54e69f6c3ff4,e5915cacb826cfadfda160f27d7e8b25,3b2fb0ad5630f9e0ff42102e8d814bbd,d766d34c2b5ca945849a3eedaf3b8ee2,c0ad4b1b4c1f736716dbd1f5e988a1f8,9858429810059c59780aa2aaecb7e3bc,a57d4e75b9a90813fedd5908da19e79a,9728d9f2e18179a5dad497437da5cb94,2a9d90f29b555ed15c42babc67b113d8,f90ebec36bd0f10f92ac100f002dd7e3,45cbbf71c3a7d62b843b1b32f11b17ed,6a91e688f8922e4553f83224d1dee633,cb990b2ed8eaf58462cd894f048dec1d,091307e0f08a6b299cb9b7217b33d840,e0feb582c70b361f3da4881d4a86e74d,dde91fc1335a71f3ae8fdea97b745a2f,0f881845163c5a72c462b1a9d8f18032,9378e43a0c920bb9e5fae8c8f447df26,41251e1e0e98f9c52c2f3677f8ce923b,5f37a3338809f89228e73ec7d0861372,e88fdb9e74b6556e1a5d3a2c9c0bea0c,83079650446b99d2b4c7f4f471820a8a,ee4a4819eaa096efe187d94c5194d33d,cfa70fbc17f2571234bb55fb53d01e44,af0cb49bd5ccbfa233c96f241b33da05,9880c3587c94cab37f89ae4df3e54927,5ddebfa7e80b46ae1e3977b32fdc13b1,aac7881dcfdc7b4da2ee06c2b24347ee -->
<!-- werkrevisor:diagrams -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>fe7a622</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/139#issuecomment-7444">the result for <code>5c507ce</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 2 finding(s) that Jev rates as probably real and severe: werkrevisor/reviewreport.py:182-184, README.md:1641-1643
- **hint** writing rules violated in the changed docs: docs/prs/2026-10-23-PR#139-assessment-after-report.md:109: paragraph with 7 sentences, more than 5
- **hint** 7 changed file(s) that neither weaken the checks, touch security nor show a risk category of the repository config according to Jev
- **hint** 1 build change(s) of low risk according to Jev: statistics/build.gradle.kts (weakens checks 0.02, risk 0.00, security 0.02)
- **hint** 10 changed file(s) agree with the PR document according to Jev
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/werkrevisor.werkbaum:209-212
- **hint** model recommends changes before merge
- **hint** model rates the risk as high (advisory: Jev judged every changed file)
### Findings
1. **[high] Content Loss** at `werkrevisor/reviewreport.py:182-184`, ORANGE, as a line comment
2. **[medium] Fold Mismatch** at `README.md:1641-1643`, ORANGE, as a line comment
3. **[medium] Diagram Omission** at `docs/werkrevisor.werkbaum:209-212`
hint; Jev: real 0.84, severity 1.9 of 3
`AGENTS.md` requires a PR that changes review steps or decisions to update the diagrams under `docs/`. This PR changes the attachment and replacement workflow and marks the `diagrams.assessment` and `diagrams.replace` items as completed, but the diff contains no diagram update. The required diagram changes for the new assessment position and same-commit replacement flow are missing.
### Classifier
10 of 10 units passed all questions (1 PR document(s)).
1 answer ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 50218, calls 1, tokens in 48464 / out 43296 (reasoning included in out), duration 645.9 s, cost 0.0665 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8768, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 5938, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 35383, cost 0.0015 USD, build file judge `jev-1.14.0` calls 8, tokens in 9944, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.3 s, model_review 643.2 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main bad4782).<br>
Reviewed head `fe7a622e4969eb3f487357848240b61434a78480` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
</sub>
### Diagrams
Drawn by a model from the diff with [PR Lens](https://github.com/coldteadotai/pr-lens): a view of what the PR touches, not a statement of what it does.



</details>
werkrevisor: ORANGE / FINDINGS for fe7a622e4969eb3f487357848240b61434a78480.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `fe7a622e4969eb3f487357848240b61434a78480`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:fe7a622e4969eb3f487357848240b61434a78480 -->
The README and the new CLI help say that --attach folds reports of earlier heads, but the implementation folds every own report except the one matching the attached head. When the branch returns to an older commit, a newer report is therefore folded too. The PR document also describes this only as a special branch-reset case and its Non-Goal broadly says earlier reports are never replaced. Align the user-facing wording with the implemented "other heads" behavior and clarify that distinction.
**[medium] Fold Mismatch** (werkrevisor)
ORANGE; Jev: real 0.73, severity 2.7 of 3
The README and the new CLI help say that `--attach` folds reports of earlier heads, but the implementation folds every own report except the one matching the attached head. When the branch returns to an older commit, a newer report is therefore folded too. The PR document also describes this only as a special branch-reset case and its Non-Goal broadly says earlier reports are never replaced. Align the user-facing wording with the implemented "other heads" behavior and clarify that distinction.
Fixed in bc40aad: README, both help texts, the Werkbaum and the PR document now say "the own reports of all other heads", also a newer one when the head went back to an earlier commit; the Non-Goal says "another commit".
Fixed in `bc40aad`: README, both help texts, the Werkbaum and the PR document now say "the own reports of all other heads", also a newer one when the head went back to an earlier commit; the Non-Goal says "another commit".
A same-head replacement sends a newly constructed body to edit_issue_comment without merging the existing body. If someone added a note or manually linked a custom SVG to an own report, the next --attach silently removes that content; a manually attached SVG can remain as an orphaned attachment. This contradicts Scenario#139.04's promise that a replacement changes only what attach wrote. The new test_a_replacement_keeps_an_svg_linked_by_hand misses this because it checks only that the asset remains, not that the manual link remains. Preserve non-tool body content and assert that the link survives.
**[high] Content Loss** (werkrevisor)
ORANGE; Jev: real 0.90, severity 3.0 of 3
A same-head replacement sends a newly constructed body to `edit_issue_comment` without merging the existing body. If someone added a note or manually linked a custom SVG to an own report, the next `--attach` silently removes that content; a manually attached SVG can remain as an orphaned attachment. This contradicts Scenario#139.04's promise that a replacement changes only what `attach` wrote. The new `test_a_replacement_keeps_an_svg_linked_by_hand` misses this because it checks only that the asset remains, not that the manual link remains. Preserve non-tool body content and assert that the link survives.
By design, documented in bc40aad: the text of the report is what attach wrote, so a replacement replaces it as a whole; merging hand edits into a new report has no safe rule. A note belongs into a comment of its own. A file attached by hand stays attached (Scenario#139.04). The PR document states this as a Non-Goal, the README names it.
By design, documented in `bc40aad`: the text of the report is what `attach` wrote, so a replacement replaces it as a whole; merging hand edits into a new report has no safe rule. A note belongs into a comment of its own. A file attached by hand stays attached (Scenario#139.04). The PR document states this as a Non-Goal, the README names it.
[high] Preserve old SVGs still linked by the replacement (Codex review)
After an initial attach, repeat it with a --checked reason linking the original diagram’s URL. The replacement retains that link, but this unconditional cleanup deletes its attachment, leaving a broken link. Reproduced with FakeGitea in memory. Retain previously uploaded assets that the replacement body still references.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Preserve old SVGs still linked by the replacement** (Codex review)
After an initial attach, repeat it with a --checked reason linking the original diagram’s URL. The replacement retains that link, but this unconditional cleanup deletes its attachment, leaving a broken link. Reproduced with FakeGitea in memory. Retain previously uploaded assets that the replacement body still references.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in 5c507ce: a replacement deletes only the old SVGs that the new text does not link; a kept one stays in hs-review-assets, so a later replacement can still delete it. test_a_replacement_keeps_an_old_svg_that_the_reason_links failed before the fix.
Fixed in `5c507ce`: a replacement deletes only the old SVGs that the new text does not link; a kept one stays in `hs-review-assets`, so a later replacement can still delete it. `test_a_replacement_keeps_an_old_svg_that_the_reason_links` failed before the fix.
The change introduces permanent deletion of existing Gitea attachments and replacement of published review comments. Incorrect cleanup can destroy review material, so it meets the irreversible-data-change criterion.
Findings
[high] Preserve old SVGs still linked by the replacement at werkrevisor/reviewreport.py:194, as a line comment
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 241636 (cached 203776) / out 2102, 88.8 s, 13 commands; reviewed head `fe7a622e4969eb3f487357848240b61434a78480`.
<!-- werkrevisor-codex:fe7a622e4969eb3f487357848240b61434a78480 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change introduces permanent deletion of existing Gitea attachments and replacement of published review comments. Incorrect cleanup can destroy review material, so it meets the irreversible-data-change criterion.
### Findings
1. **[high] Preserve old SVGs still linked by the replacement** at `werkrevisor/reviewreport.py:194`, as a line comment
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 241636 (cached 203776) / out 2102, 88.8 s, 13 commands; reviewed head `fe7a622e4969eb3f487357848240b61434a78480`.
</sub>
werkrevisor: GREEN / PASS for 5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4.
The result comment of werkrevisor holds the details.
werkrevisor: GREEN / PASS for `5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4 -->
ai-reviewer
removed review request for mi 2026-10-23 17:36:22 +02:00
The change permanently deletes existing Gitea diagram attachments when replacing a report. This introduces irreversible changes to stored data and therefore requires human review.
No findings.
The merge waits for the status ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
Model `gpt-6-astra`, effort high, tokens in 447027 (cached 392832) / out 2460, 100.6 s, 23 commands; reviewed head `5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4`.
<!-- werkrevisor-codex:5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change permanently deletes existing Gitea diagram attachments when replacing a report. This introduces irreversible changes to stored data and therefore requires human review.
No findings.
The merge waits for the status `ai-review/codex`: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.
<sub>
Model `gpt-6-astra`, effort high, tokens in 447027 (cached 392832) / out 2460, 100.6 s, 23 commands; reviewed head `5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4`.
</sub>
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.
--checkedmoves from the top of the comment to a closing section "Assessment of the findings" after the report.--attachfor the same commit replaces the own report; a report of a new commit folds the earlier ones.🤖 Generated with Claude Code
WIP: werkrevisor 0.65.3: draft-review --attach --checked puts the assessment of the findings after the reportto WIP: werkrevisor 0.66.0: draft-review --attach puts the assessment after the report and replaces the report of the same commit🟢 werkrevisor GREEN for
6afb1dd, superseded by the result for020d14e🟢 werkrevisor: GREEN / PASS
Gate: approved by werkrevisor; merge waits for 2 open hint(s): reply to each line comment and resolve it, then restart the review or push a commit.
Change kind:
mixed.Reasons
Findings
werkrevisor/draftreview.py:181, hint, as a line commentClassifier
8 of 8 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40917, duration 724.6 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6742, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26040, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.3 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 722.7 s, config: defaults + host + repository (.werkrevisor.toml at main2 answers ignored because of a confidence below [classifier] min_confidence.
284f80e).Reviewed head `6afb1dd3ac9f78ecdc749f33518101f066dd191d` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
werkrevisor: GREEN / PASS for
6afb1dd3ac9f78ecdc749f33518101f066dd191d.The result comment of werkrevisor holds the details.
@@ -0,0 +90,4 @@## Open Questions- [x] Where does the reason go: one comment with a closing section, a second comment, a table per finding, or a `<details>` block?Writing rule: line longer than 128 characters (130) (werkrevisor writing rule)
Fix the line, or reply why it stays, and resolve this comment.
Fixed in
020d14e: the line is wrapped after a comma.@@ -179,3 +179,3 @@parser.add_argument("pr", help="a PR number of the default repository, or the URL of a PR on the configured server")parser.add_argument("--attach", action="store_true",help="post the checked draft and its diagrams to the PR, without a new review")help="post the checked draft and its diagrams to the PR, without a new review; "[medium] Claimed implementation is missing in the file (werkrevisor)
hint
Jev compared the diff of this file with the PR document: Claimed implementation is missing in the file 0.82.
Fix the PR document or the code, or reply why the file belongs to the PR, and resolve this comment.
File fingerprint
f7e6d41bb0ff.Fixed in
020d14e: the Solution of the PR document now names the help texts inwerkrevisor/draftreview.py.New commits pushed, approval review dismissed automatically according to repository settings
🟢 werkrevisor GREEN for
020d14e, superseded by the result forff0dd74🟢 werkrevisor: GREEN / PASS
Gate: approved by werkrevisor; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind:
mixed.Reasons
6afb1ddnot carried over: 1 approved block(s) are missingClassifier
8 of 8 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 40633, duration 725.3 s, cost unknown, classifier `jev-1.14.0` calls 8, tokens in 6791, cost 0.0003 USD, PR document check `jev-1.14.0` calls 9, tokens in 26481, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 7864, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.5 s, model_review 722.9 s, config: defaults + host + repository (.werkrevisor.toml at main1 answer ignored because of a confidence below [classifier] min_confidence.
bad4782).Reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec` against base `284f80eeae1941db4f8ef2b56088533e1b710d98`, werkrevisor 0.65.0.
werkrevisor: GREEN / PASS for
020d14eff64b7c49a6347dc00275cf883ca7f8ec.The result comment of werkrevisor holds the details.
Codex review of
020d14eff64b7c49a6347dc00275cf883ca7f8ec@@ -126,0 +175,4 @@raise# The new body links only the new SVGs._delete_assets(gitea, same["id"], old)return same.get("html_url", "")[medium] Replacing a previously folded report skips folding the superseded report (Codex review)
After attaching reports for commits A and B, reset the PR head to A and attach again. The replacement unfolds A, but this early return skips the folding loop, leaving B unfolded too. Reproduced with FakeGitea: both reports remain open, contrary to the promised single current report. Fold the other reports after replacement as well.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
ff0dd74: a replacement folds the reports of the other heads too;test_a_replaced_report_folds_the_reports_of_other_headsfailed before the fix.Codex review: critical
The change permanently deletes existing Gitea comment attachments when replacing a report. A mistake in selecting those attachments could irreversibly destroy stored review artifacts.
Findings
werkrevisor/reviewreport.py:178, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 265620 (cached 232960) / out 2382, 101.2 s, 12 commands; reviewed head `020d14eff64b7c49a6347dc00275cf883ca7f8ec`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.020d14eff6toff0dd748d8New commits pushed, approval review dismissed automatically according to repository settings
🟠 werkrevisor ORANGE for
ff0dd74, superseded by the result for77bb9d9🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
020d14enot carried over: 7 approved block(s) are missingFindings
[medium] Edit Failure at
werkrevisor/reviewreport.py:172-175, ORANGE, as a line comment[medium] Asset IDs at
tests/fakes.py:193-195, hint, as a line commentClassifier
8 of 8 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 41431, calls 1, tokens in 39971 / out 47409 (reasoning included in out), duration 324.6 s, cost 0.0689 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6814, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3359, cost 0.0001 USD, PR document check `jev-1.14.0` calls 9, tokens in 27370, cost 0.0011 USD, build file judge `jev-1.14.0` calls 7, tokens in 8240, cost 0.0003 USD, phases: path_judge 0.4 s, classifier 0.3 s, doc_check 0.5 s, context 0.3 s, model_review 322.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main1 answer ignored because of a confidence below [classifier] min_confidence.
bad4782).Reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
werkrevisor: ORANGE / FINDINGS for
ff0dd748d8b3002c896e6222b7ac3b5c0173099b.The result comment of werkrevisor holds the details.
@@ -191,3 +191,3 @@self.writes.append("asset")comment = next(c for c in self.comments if c.get("id") == comment_id)asset = {"name": name, "size": len(content), "content_type": content_type,asset_id = sum(len(c.get("assets", ())) for c in self.comments) + 1[medium] Asset IDs (werkrevisor)
hint; Jev: real 0.76, severity 2.1 of 3
The asset ID is derived from the current asset count, so it is reused after deletions. After two replacements of the same comment, deleting the old asset can also delete the newly uploaded one because both have the same ID. The URL also omits the asset identity, so the test cannot prove that the body links the new attachment. Use a monotonic ID or UUID and include it in the fake URL.
Fixed in
4578286: the fake counts asset IDs up and puts the ID into the URL, as Gitea never reuses them; the replacement test now replaces twice and checks the URL of the new asset.@@ -135,2 +170,3 @@body, uploaded = _upload(gitea, same["id"], directory, names, body)try:gitea.delete_issue_comment(comment["id"])gitea.edit_issue_comment(same["id"], marker + "\n" + body)[medium] Edit Failure (werkrevisor)
ORANGE; Jev: real 0.80, severity 3.0 of 3
The exception path assumes a failed comment edit means the comment was not changed. If Gitea applies the edit but its response is lost, the live comment references the newly uploaded assets and this cleanup deletes them, leaving broken SVGs. Keep the new assets until the resulting comment has been verified, or otherwise make the replacement retry-safe.
Fixed in
4578286: after a failed edit,attachreads the comment again and deletes only the new SVGs that it does not link; if the read fails too, it keeps them. The old SVGs go only if the new body does not link them.test_an_edit_applied_despite_a_lost_response_keeps_its_svgsfailed before the fix.Codex review of
ff0dd748d8b3002c896e6222b7ac3b5c0173099b@@ -141,0 +174,4 @@_delete_assets(gitea, same["id"], uploaded)raise# The new body links only the new SVGs._delete_assets(gitea, same["id"], old)[high] Replacement deletes unrelated attachments (Codex review)
oldcontains every attachment returned bylist_comment_assets, and this call deletes all of them. If a user added supporting logs or screenshots to the report comment, repeating--attachpermanently deletes those files along with the generated SVGs. An in-memory reproduction confirms this. Cleanup must restrict deletion to the generated attachments being replaced.Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
77bb9d9: a replacement deletes only the SVGs of PR Lens that the old report linked and the new one does not; a file that someone added to the comment stays.test_a_replacement_keeps_a_file_added_by_handfailed before the fix.Codex review: critical
The change introduces irreversible deletion of existing comment attachments. Incorrect cleanup can destroy manually added evidence, which the current tests do not cover.
Findings
werkrevisor/reviewreport.py:177, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 292601 (cached 252672) / out 2182, 113.4 s, 12 commands; reviewed head `ff0dd748d8b3002c896e6222b7ac3b5c0173099b`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.🟠 werkrevisor ORANGE for
77bb9d9, superseded by the result for79591ad🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Attachment limit at
werkrevisor/reviewreport.py:173-189, ORANGE, as a line comment[medium] Blank lines at
werkrevisor/reviewreport.py:83-85, hint, as a line comment[low] Earlier-report wording at
docs/prs/2026-10-23-PR#139-assessment-after-report.md:25hint
The Non-Goals states categorically that the report of an earlier commit is not replaced, but the implemented rollback path replaces exactly that report when its commit becomes the current head. Clarify that the non-replacement rule applies only while another head is current, so the documented contract does not contradict the tested behavior.
Classifier
7 of 8 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 48753, calls 1, tokens in 47045 / out 22015 (reasoning included in out), duration 392.3 s, cost 0.0405 USD (reported), classifier `jev-1.14.0` calls 8, tokens in 6894, cost 0.0003 USD, finding judge `jev-1.14.0` calls 2, tokens in 3740, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 32031, cost 0.0013 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.4 s, doc_check 0.5 s, context 0.3 s, model_review 389.9 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at mainbad4782).Reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
werkrevisor: ORANGE / FINDINGS for
77bb9d936112c5bcf4eb5956def14657b2b0ff36.The result comment of werkrevisor holds the details.
@@ -92,2 +82,2 @@header[1:1] = [""] + blockreturn "\n".join(header) + sep + rest# Only the header holds the draft line; a finding may quote the same words.header = [line for line in head.split("\n") if not line.startswith(DRAFT_LINE)][medium] Blank lines (werkrevisor)
hint; Jev: real 0.82, severity 1.6 of 3
Removing the draft line leaves both neighboring empty lines in the header. The cleanup checks the previous line of the original list rather than the already-filtered list, so
confirm()emits three consecutive newlines before the first report section. This adds an unintended blank line to every checked report and makestest_a_reason_follows_the_report_as_assessmentfail itsassertNotIn("\\n\\n\\n", body)check. Collapse the blank lines using the previously retained element or remove the blank adjacent to the deleted draft line.Does not hold: the comprehension in line 82 reads
headerafter the draft line is filtered out in line 81, soheader[i - 1]is the previous retained line and the blank line after the removed draft line goes.test_a_reason_follows_the_report_as_assessmentasserts no\n\n\nand passes in the pinned PR-Agent image (910 tests OK at79591ad). No change.@@ -134,1 +171,3 @@except Exception:same = next((c for c in reversed(reports) if REPORT_MARKER.search(c["body"]).group(1) == head), None)if same:old, old_body = gitea.list_comment_assets(same["id"]) or [], same["body"][medium] Attachment limit (werkrevisor)
ORANGE; Jev: real 0.79, severity 2.9 of 3
A replacement uploads all new SVG assets before deleting the old generated assets, so the comment temporarily contains both sets. If the old report is already at Gitea's per-comment attachment limit, the new upload is rejected and the same-head replacement cannot proceed. This affects reports with several diagrams and is not exposed by the unlimited fake. Avoid the temporary over-limit state, such as by reusing suitable existing assets or providing a safe fallback.
No change: a rejected upload is already the safe fallback.
_uploaddeletes the SVGs it uploaded, the comment keeps its old body and old SVGs, and--attachexits with the error (test_a_failed_replacement_keeps_the_report_and_its_svgs). Gitea's[attachment] MAX_FILESlimits one upload form; to my knowledge the API for comment assets counts no attachments per comment. A draft has a few PR Lens diagrams, so old and new together stay small. Left for the human to judge.Codex review: critical
The change overwrites existing review comments and permanently deletes their previous SVG attachments. This introduces irreversible changes to existing review data, requiring human review under the stated criteria.
No findings.
The merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 360336 (cached 315776) / out 2745, 135.5 s, 18 commands; reviewed head `77bb9d936112c5bcf4eb5956def14657b2b0ff36`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.🟠 werkrevisor ORANGE for
79591ad, superseded by the result forfe7a622🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[high] Asset Deletion at
werkrevisor/reviewreport.py:186-189, ORANGE, as a line comment[medium] Stale Body at
werkrevisor/reviewreport.py:167-210, ORANGE, as a line comment[low] Ambiguous Failure at
docs/prs/2026-10-23-PR#139-assessment-after-report.md:62-73, hint, as a line commentClassifier
10 of 10 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 49061, calls 1, tokens in 47331 / out 43261 (reasoning included in out), duration 656.3 s, cost 0.0661 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8705, cost 0.0004 USD, finding judge `jev-1.14.0` calls 2, tokens in 4284, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 33741, cost 0.0014 USD, build file judge `jev-1.14.0` calls 8, tokens in 9422, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.4 s, model_review 653.5 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main3 answers ignored because of a confidence below [classifier] min_confidence.
bad4782).Reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
werkrevisor: ORANGE / FINDINGS for
79591ad69bd5ca48d99106774c6c3523f8625f13.The result comment of werkrevisor holds the details.
@@ -0,0 +59,4 @@- [test_reviewreport.AttachTest.test_a_second_post_for_the_same_head_replaces_the_report](../../tests/test_reviewreport.py)#### Scenario#139.03: a failed replacement leaves the old report[low] Ambiguous Failure (werkrevisor)
hint
The scenario heading promises that a failed replacement leaves the old report, but the implementation also reports failure when the edit was applied and only its response was lost; the referenced lost-response test shows that the new report then remains. The Given/When/Then only states that links reference attached SVGs and never identifies which report survives. Split the rejected edit and unknown-response outcomes so the documented contract is unambiguous.
Fixed in
fe7a622: Scenario#139.03 is now "a failed replacement leaves no broken links": the comment holds the old or the new report, and each SVG that it links is attached; the When names both failures.@@ -121,1 +164,4 @@raise AttachError(f"the draft links SVGs that are not next to it: {', '.join(missing)}")login = (gitea.current_user() or {}).get("login")# Only the own reports: a report of someone else is theirs to replace.reports = [c for c in gitea.list_issue_comments(number) or ()[medium] Stale Body (werkrevisor)
ORANGE; Jev: real 0.83, severity 3.0 of 3
reportscaptures each earlier comment body before the asset uploads and edits, butfoldlater writes that stale snapshot back with a full-body PATCH. If an earlier report is edited while attachments are being uploaded, that edit is silently discarded. Re-read and preserve the current body before folding it.Fixed in
fe7a622:attachreads each earlier report again right before it folds it.test_a_fold_keeps_an_edit_made_meanwhilefailed before the fix.@@ -141,0 +183,4 @@if current is not None:_delete_assets(gitea, same["id"], _unlinked(uploaded, current))raise# Only the SVGs that the old report linked go; a file that someone added to the comment stays.[high] Asset Deletion (werkrevisor)
ORANGE; Jev: real 0.84, severity 3.0 of 3
The cleanup treats every old attachment whose name starts with
pr-lens-and whose URL occurs in the old body as tool-generated. A user-addedpr-lens-custom.svgthat was linked in that body is therefore deleted during replacement, contradicting the promise that files added by hand remain. Track the asset IDs uploaded byattachinstead of inferring ownership from the filename and link.Fixed in
fe7a622: the comment names the IDs of the SVGs thatattachuploaded in<!-- hs-review-assets:<ids> -->; a replacement deletes only those.test_a_replacement_keeps_an_svg_linked_by_handfailed before the fix.Codex review: critical
The change overwrites existing review comments and permanently deletes their previous diagram attachments. This introduces irreversible changes to existing data, so human review is required.
No findings.
The merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 313750 (cached 274944) / out 2457, 113.1 s, 7 commands; reviewed head `79591ad69bd5ca48d99106774c6c3523f8625f13`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.🟠 werkrevisor ORANGE for
fe7a622, superseded by the result for5c507ce🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[high] Content Loss at
werkrevisor/reviewreport.py:182-184, ORANGE, as a line comment[medium] Fold Mismatch at
README.md:1641-1643, ORANGE, as a line comment[medium] Diagram Omission at
docs/werkrevisor.werkbaum:209-212hint; Jev: real 0.84, severity 1.9 of 3
AGENTS.mdrequires a PR that changes review steps or decisions to update the diagrams underdocs/. This PR changes the attachment and replacement workflow and marks thediagrams.assessmentanddiagrams.replaceitems as completed, but the diff contains no diagram update. The required diagram changes for the new assessment position and same-commit replacement flow are missing.Classifier
10 of 10 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 50218, calls 1, tokens in 48464 / out 43296 (reasoning included in out), duration 645.9 s, cost 0.0665 USD (reported), classifier `jev-1.14.0` calls 10, tokens in 8768, cost 0.0004 USD, finding judge `jev-1.14.0` calls 3, tokens in 5938, cost 0.0002 USD, PR document check `jev-1.14.0` calls 10, tokens in 35383, cost 0.0015 USD, build file judge `jev-1.14.0` calls 8, tokens in 9944, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.3 s, model_review 643.2 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main1 answer ignored because of a confidence below [classifier] min_confidence.
bad4782).Reviewed head `fe7a622e4969eb3f487357848240b61434a78480` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
Diagrams
Drawn by a model from the diff with PR Lens: a view of what the PR touches, not a statement of what it does.
werkrevisor: ORANGE / FINDINGS for
fe7a622e4969eb3f487357848240b61434a78480.The result comment of werkrevisor holds the details.
@@ -1639,3 +1639,3 @@`tools/review-report --attach` posts the checked draft instead, without a new review:a comment of the PR with the SVGs as attachments, under the account of the token.It refuses a draft that still has its line "> **Draft:** …", is for another head, or is posted already.It refuses a draft that still has its line "> **Draft:** …", or is for another head.[medium] Fold Mismatch (werkrevisor)
ORANGE; Jev: real 0.73, severity 2.7 of 3
The README and the new CLI help say that
--attachfolds reports of earlier heads, but the implementation folds every own report except the one matching the attached head. When the branch returns to an older commit, a newer report is therefore folded too. The PR document also describes this only as a special branch-reset case and its Non-Goal broadly says earlier reports are never replaced. Align the user-facing wording with the implemented "other heads" behavior and clarify that distinction.Fixed in
bc40aad: README, both help texts, the Werkbaum and the PR document now say "the own reports of all other heads", also a newer one when the head went back to an earlier commit; the Non-Goal says "another commit".@@ -0,0 +106,4 @@- `werkrevisor/reviewreport.py`: `confirm` removes the draft line from the headerand appends the reason as plain text under "### Assessment of the findings",after the last section of the report and before the usage line.- `werkrevisor/reviewreport.py`: `attach` looks for own comments with the marker `<!-- hs-review:<sha> -->`.Writing rule: paragraph with 7 sentences, more than 5 (werkrevisor writing rule)
Fix the line, or reply why it stays, and resolve this comment.
Fixed in
bc40aad: the item is split in two, the post or replacement and the fold.@@ -135,0 +179,4 @@own = ASSETS_MARKER.search(same["body"])own = {int(i) for i in own.group(1).split(",") if i} if own else set()old = [a for a in gitea.list_comment_assets(same["id"]) or [] if a.get("id") in own]body, uploaded = _upload(gitea, same["id"], directory, names, body)[high] Content Loss (werkrevisor)
ORANGE; Jev: real 0.90, severity 3.0 of 3
A same-head replacement sends a newly constructed body to
edit_issue_commentwithout merging the existing body. If someone added a note or manually linked a custom SVG to an own report, the next--attachsilently removes that content; a manually attached SVG can remain as an orphaned attachment. This contradicts Scenario#139.04's promise that a replacement changes only whatattachwrote. The newtest_a_replacement_keeps_an_svg_linked_by_handmisses this because it checks only that the asset remains, not that the manual link remains. Preserve non-tool body content and assert that the link survives.By design, documented in
bc40aad: the text of the report is whatattachwrote, so a replacement replaces it as a whole; merging hand edits into a new report has no safe rule. A note belongs into a comment of its own. A file attached by hand stays attached (Scenario#139.04). The PR document states this as a Non-Goal, the README names it.Codex review of
fe7a622e4969eb3f487357848240b61434a78480@@ -141,0 +191,4 @@if current is not None:_delete_assets(gitea, same["id"], _unlinked(uploaded, current))raise_delete_assets(gitea, same["id"], old)[high] Preserve old SVGs still linked by the replacement (Codex review)
After an initial attach, repeat it with a --checked reason linking the original diagram’s URL. The replacement retains that link, but this unconditional cleanup deletes its attachment, leaving a broken link. Reproduced with FakeGitea in memory. Retain previously uploaded assets that the replacement body still references.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
5c507ce: a replacement deletes only the old SVGs that the new text does not link; a kept one stays inhs-review-assets, so a later replacement can still delete it.test_a_replacement_keeps_an_old_svg_that_the_reason_linksfailed before the fix.Codex review: critical
The change introduces permanent deletion of existing Gitea attachments and replacement of published review comments. Incorrect cleanup can destroy review material, so it meets the irreversible-data-change criterion.
Findings
werkrevisor/reviewreport.py:194, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 241636 (cached 203776) / out 2102, 88.8 s, 13 commands; reviewed head `fe7a622e4969eb3f487357848240b61434a78480`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.🟢 werkrevisor: GREEN / PASS
Change kind:
mixed.Reasons
Classifier
10 of 10 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM failed (TimeoutError), tokens counted before the call 50921, duration 725.1 s, cost unknown, classifier `jev-1.14.0` calls 10, tokens in 8826, cost 0.0004 USD, PR document check `jev-1.14.0` calls 10, tokens in 36604, cost 0.0015 USD, build file judge `jev-1.14.0` calls 8, tokens in 10196, cost 0.0004 USD, phases: path_judge 0.4 s, classifier 0.5 s, doc_check 0.5 s, context 0.3 s, model_review 722.8 s, config: defaults + host + repository (.werkrevisor.toml at main1 answer ignored because of a confidence below [classifier] min_confidence.
bad4782).Reviewed head `5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4` against base `bad4782b99657b8a662db8b9333722c04619962e`, werkrevisor 0.65.2.
werkrevisor: GREEN / PASS for
5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4.The result comment of werkrevisor holds the details.
Codex review: critical
The change permanently deletes existing Gitea diagram attachments when replacing a report. This introduces irreversible changes to stored data and therefore requires human review.
No findings.
The merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 447027 (cached 392832) / out 2460, 100.6 s, 23 commands; reviewed head `5c507ceefbc278d1896f4c6f5c4a5c884d4b28e4`.ai-review/codex: every line comment resolved, and the approval of a human for a critical PR or for a finding that is only here.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.