See docs/prs for the PR document.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-code
changed title from WIP: diagrams of PR Lens in the review comment to werkrevisor 0.50.0: diagrams of PR Lens in the result comment2026-10-18 20:14:52 +02:00
claude-code
marked the pull request as work in progress 2026-10-18 20:19:05 +02:00
claude-code
marked the pull request as ready for review 2026-10-18 20:19:09 +02:00
hint 12 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 24 changed file(s) agree with the PR document according to Jev
hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
hint files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
This condition does not check use_llm. With diagrams enabled and an OpenRouter key available, --no-llm still invokes the diagram model, transmitting the diff and incurring charges despite requesting deterministic rules only. Reproduced with use_llm=False: the review reports 'skipped (--no-llm)' but draw_diagrams is called.
Fix it, or reply why it does not hold, and resolve this comment.
**[medium] Diagram generation ignores --no-llm** (Codex review)
This condition does not check use_llm. With diagrams enabled and an OpenRouter key available, --no-llm still invokes the diagram model, transmitting the diff and incurring charges despite requesting deterministic rules only. Reproduced with use_llm=False: the review reports 'skipped (--no-llm)' but draw_diagrams is called.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
[high] Diagram generation bypasses the secret-scan veto (Codex review)
When the secret scan detects credentials, the review finishes YELLOW and skips its model calls. Diagram generation still runs and forwards the raw diff to OpenRouter. An in-memory reproduction confirmed that a diff containing a detected password reaches draw_diagrams unchanged, defeating the existing protection against spreading leaked secrets.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Diagram generation bypasses the secret-scan veto** (Codex review)
When the secret scan detects credentials, the review finishes YELLOW and skips its model calls. Diagram generation still runs and forwards the raw diff to OpenRouter. An in-memory reproduction confirmed that a diff containing a detected password reaches draw_diagrams unchanged, defeating the existing protection against spreading leaked secrets.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in e716ea6: only a fresh review without a secrets reason may draw; a rerun only links SVGs that are attached already, since it does not know whether its first run found a secret. Scenario#121.07, red/green: test_a_possible_secret_keeps_the_diff_from_pr_lens failed before the fix.
Fixed in `e716ea6`: only a fresh review without a `secrets` reason may draw; a rerun only links SVGs that are attached already, since it does not know whether its first run found a secret. Scenario#121.07, red/green: `test_a_possible_secret_keeps_the_diff_from_pr_lens` failed before the fix.
The change adds third-party code and a new outbound model-call path inside the credential-bearing review process. Mistakes can disclose secrets, and the mocked tests do not cover this security boundary.
Findings
[high] Diagram generation bypasses the secret-scan veto at werkrevisor/cli.py:1262, as a line comment
[medium] Diagram generation ignores --no-llm at werkrevisor/cli.py:1124, 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 373526 (cached 301952) / out 2533, 80.2 s, 14 commands; reviewed head `babb25ace2f60d9b44f0def5a2f3aa2233c60db2`.
<!-- werkrevisor-codex:babb25ace2f60d9b44f0def5a2f3aa2233c60db2 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
<!-- werkrevisor-folded -->
<details><summary>⚠️ werkrevisor ERROR for <code>?</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6366">the result for <code>34a7b98</code></a></summary>
## Codex review: critical
The change adds third-party code and a new outbound model-call path inside the credential-bearing review process. Mistakes can disclose secrets, and the mocked tests do not cover this security boundary.
### Findings
1. **[high] Diagram generation bypasses the secret-scan veto** at `werkrevisor/cli.py:1262`, as a line comment
2. **[medium] Diagram generation ignores --no-llm** at `werkrevisor/cli.py:1124`, 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 373526 (cached 301952) / out 2533, 80.2 s, 14 commands; reviewed head `babb25ace2f60d9b44f0def5a2f3aa2233c60db2`.
</sub>
</details>
hint 12 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.01)
hint 24 changed file(s) agree with the PR document according to Jev
hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
hint files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
Gate: no human review requested; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind: mixed.
Reasons
YELLOW risky build changes according to Jev: .dockerignore (weakens checks 0.10, risk 1.60, security 0.02), Dockerfile (weakens checks 0.10, risk 1.88, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
hint 12 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.01)
hint 24 changed file(s) agree with the PR document according to Jev
hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
hint files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
Classifier
14 of 14 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 77519, calls 1, tokens in 74781 / out 18890 (reasoning included in out), duration 206.4 s, cost 0.0451 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11815, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 23759 / out 493, cost 0.0005 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 108918, cost 0.0046 USD, build file judge `jev-1.13.0` calls 17, tokens in 19726, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 0.9 s, doc_check 1.6 s, context 8.4 s, model_review 193.7 s, config: defaults + host + repository (.werkrevisor.toml at main 4685c8d).
Reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f` against base `4685c8db840b552add7486260d5a6f0ed7ee9d35`, werkrevisor 0.49.1.
<!-- werkrevisor:a33b894edda3b4e015e49c8824b5e9d5e701516f -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:6a5dd6d15a75ce527b81c68c2818c813,d08f070eb191140febbed9f8337e84c4,36931004656593df9fa3e3ebc963e9d2,b7bfed626bc792a58cc5d643c2e8c4f9,fd005bda47e317b42d39a976c2a11daf,cfb5b10cb3cf703bf6ed41383d265d22,23c03ab2929fa10aa09d24ae9bce8090,97ff1748d79afbd3818e3a037f781eeb,db20165e1d03111a86c2c21f791b17ff,c4a55b1253ce650869e43668f1ca33a8,86b61de5e5dd9a3913e228b031e6b815,c7426376be99af7fb99445a20381c4e3,512615261df3588425376f93a6498cf1,83cf952851e2a6f8031616af674d1a53,5bdab77a421047471ebd4aece905c38c,03196a062679ab178fd54ab43daf0474,61f9f80cd1e1fcda02b28d6474c9c8ce,5fdc271260963c60959facd73a6b555a,768b1b55a99fb5326c78479d06997b98,0bcba3f2d2e7b4080a0d510eb3d210dd,cd5e595a700c6b3192f1a7028f8f5a57,da2e8d79aa0010083b40f6a4d2f76dba,e55ee8044e35cbe55abe2fe43dbc9c4b,787503c8d9ba5e44f388d566b30d3849,1513afe6c5523825ba9d22cf2dd52dc1,7cb5e52706b3ff04396ac03c416cc09a,91f33c237e1db63164dfb39fb44f4c9c,4ae0f702d1e3515bbbe58f96db668098,438e9746e9b295dfe8a3685c48935f4f,7d7bb43f72075a5e171dc02dcf23780d,373d148295aa718cde37a9d93f8cca3f,7822582c202c2521fea3fd667c436a31,d0a25d8c07e95d646d21bec9d51577fa,a6ebd6850f5ced07f5ce1f811a44831c,e1529479c46d63b7947586c7a37ba709,28b4c5d2aad07665bce904a681cbfdd4,3c60cbdc4dd48e2a5b08e7d9de4865c5,47d792ef5e5d855f89c030da011a799b,575088c5a9a867b44a5f854105399a33,924fe5dc830391b398ff7b9fc2d8bd22,8f3239045b94d86ba67cd4a7f53d0bae,608881546380d8db17664576d17a2482,a20cbd8ee07e5f0bf20d1ec874296375,7fa1cdc645f02745f6fb26abe312e75e,9c9b688f26e5a3b3b44eb0f5336814f4,43580384cba6f832d8871d649d923501,d8f5a31f10a8fe7db09536973ec42348,6dc3747662f2ee4f41311ef93ae1e0f8,b452fc73a39e68f4cc438c73a0bfcbbd,12a0e07c4646558ca0e39445bae26427,9d54c899562ad34810f0c2118a0fff42,2086857163b30bf27a8311ca587e8939,5fd168200f4a61084cb520b65391233c,ace9bd022e0ffd6415788fae898bd5d0,36461bb4f9ef83927d1626224cfb8c48,e8a0e2482fd99a2898e9d7e3f6c698da,fd849b2a094720de035c6645665938cd,e6c0b9a6aecd73a81379140cb953995e,bddbf4148d3c48a87349acbb8f048c8d,ee659a7a8a8168f1cd8b768f6eb3a784,2a526341ae388b9a485a392b293e25cb,351fc8c9957d07c225622497a4ae8135,846f9429cc2b163fd4c6016cc4804887,7acab543a4c8952784ef552794aa3396 -->
<!-- werkrevisor-folded -->
<details><summary>🟡 werkrevisor YELLOW for <code>a33b894</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6384">the result for <code>e716ea6</code></a></summary>
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Gate: no human review requested; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind: `mixed`.
### Reasons
- **YELLOW** risky build changes according to Jev: .dockerignore (weakens checks 0.10, risk 1.60, security 0.02), Dockerfile (weakens checks 0.10, risk 1.88, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
- **hint** 12 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.01)
- **hint** 24 changed file(s) agree with the PR document according to Jev
- **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
- **hint** files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
### Classifier
14 of 14 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 77519, calls 1, tokens in 74781 / out 18890 (reasoning included in out), duration 206.4 s, cost 0.0451 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11815, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 23759 / out 493, cost 0.0005 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 108918, cost 0.0046 USD, build file judge `jev-1.13.0` calls 17, tokens in 19726, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 0.9 s, doc_check 1.6 s, context 8.4 s, model_review 193.7 s, config: defaults + host + repository (.werkrevisor.toml at main 4685c8d).<br>
Reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f` against base `4685c8db840b552add7486260d5a6f0ed7ee9d35`, werkrevisor 0.49.1.
</sub>
</details>
This condition does not check use_llm. With diagrams enabled and publishing allowed, --no-llm still invokes PR Lens and its external model, transmitting the diff and incurring charges despite the request to apply deterministic rules only. Reproduced with use_llm=False.
Fix it, or reply why it does not hold, and resolve this comment.
**[medium] Diagram generation ignores --no-llm** (Codex review)
This condition does not check use_llm. With diagrams enabled and publishing allowed, --no-llm still invokes PR Lens and its external model, transmitting the diff and incurring charges despite the request to apply deterministic rules only. Reproduced with use_llm=False.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in e716ea6, as in the same finding on babb25a: drawing needs use_llm, a fresh review and no secrets reason (Scenario#121.07, Scenario#121.08, each with red/green).
Fixed in `e716ea6`, as in the same finding on `babb25a`: drawing needs `use_llm`, a fresh review and no `secrets` reason (Scenario#121.07, Scenario#121.08, each with red/green).
[high] Diagram generation bypasses the secret-scan guard (Codex review)
With diagrams enabled, a diff flagged by the secret scanner produces YELLOW and skips the review model, but still reaches this call unchanged and is sent to OpenRouter. Reproduced with a private-key marker: the review model received zero calls while the diagram generator received the raw diff. This defeats the existing protection against sending detected secrets to external models.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Diagram generation bypasses the secret-scan guard** (Codex review)
With diagrams enabled, a diff flagged by the secret scanner produces YELLOW and skips the review model, but still reaches this call unchanged and is sent to OpenRouter. Reproduced with a private-key marker: the review model received zero calls while the diagram generator received the raw diff. This defeats the existing protection against sending detected secrets to external models.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in e716ea6, as in the same finding on babb25a: drawing needs use_llm, a fresh review and no secrets reason (Scenario#121.07, Scenario#121.08, each with red/green).
Fixed in `e716ea6`, as in the same finding on `babb25a`: drawing needs `use_llm`, a fresh review and no `secrets` reason (Scenario#121.07, Scenario#121.08, each with red/green).
The change introduces third-party Node.js code into the credential-bearing review process and a new path that sends PR contents to an external model. Mistakes can expose secrets, which the mocked tests do not establish protection against.
Findings
[high] Diagram generation bypasses the secret-scan guard at werkrevisor/cli.py:1262, as a line comment
[medium] Diagram generation ignores --no-llm at werkrevisor/cli.py:1124, 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 466369 (cached 392192) / out 2579, 71.9 s, 16 commands; reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f`.
<!-- werkrevisor-codex:a33b894edda3b4e015e49c8824b5e9d5e701516f -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
<!-- werkrevisor-folded -->
<details><summary>⚠️ werkrevisor ERROR for <code>?</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6384">the result for <code>e716ea6</code></a></summary>
## Codex review: critical
The change introduces third-party Node.js code into the credential-bearing review process and a new path that sends PR contents to an external model. Mistakes can expose secrets, which the mocked tests do not establish protection against.
### Findings
1. **[high] Diagram generation bypasses the secret-scan guard** at `werkrevisor/cli.py:1262`, as a line comment
2. **[medium] Diagram generation ignores --no-llm** at `werkrevisor/cli.py:1124`, 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 466369 (cached 392192) / out 2579, 71.9 s, 16 commands; reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f`.
</sub>
</details>
claude-code
changed title from werkrevisor 0.50.0: diagrams of PR Lens in the result comment to werkrevisor 0.52.0: diagrams of PR Lens in the result comment2026-10-18 20:42:41 +02:00
The stage base adds Debian's nodejs and the packages of tools/pr-lens/package-lock.json;
npm stays in a build stage. The base archive name holds a hash of the base stages and the lockfile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
werkrevisor/pr_lens.mjs draws them from the diff with the pinned PR Lens;
werkrevisor attaches the light SVGs to its result comment after the verdict.
A failure only prints a line; a rerun on the same head reuses the attached SVGs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only a fresh review with the model and without a possible secret draws; a rerun only links attached SVGs.
Found by the Codex review of babb25a.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
YELLOW possible secrets in added lines: tests/test_prlens.py:104 (private_key), tests/test_prlens.py:123 (private_key)
YELLOW changed files not judged by Jev (possible secrets in the diff): .dockerignore, Dockerfile, statistics/build.gradle.kts and 14 more
hint the PR document was not compared with the diff: possible secrets in the diff
Usage: model `openrouter/minimax/minimax-m3`, LLM skipped (possible secrets in the diff), duration 2.1 s, no model call, cost 0 USD, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).
Reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
<!-- werkrevisor:e716ea6c87a9d90eac9e4930551ab6278fb43fc9 -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:6a5dd6d15a75ce527b81c68c2818c813,d08f070eb191140febbed9f8337e84c4,36931004656593df9fa3e3ebc963e9d2,358dfaf22bbde637138d66e4086d5817,fd005bda47e317b42d39a976c2a11daf,cfb5b10cb3cf703bf6ed41383d265d22,23c03ab2929fa10aa09d24ae9bce8090,97ff1748d79afbd3818e3a037f781eeb,db20165e1d03111a86c2c21f791b17ff,c4a55b1253ce650869e43668f1ca33a8,86b61de5e5dd9a3913e228b031e6b815,c7426376be99af7fb99445a20381c4e3,4e68f592885c14cffac308c67e33a1cf,83cf952851e2a6f8031616af674d1a53,5bdab77a421047471ebd4aece905c38c,03196a062679ab178fd54ab43daf0474,61f9f80cd1e1fcda02b28d6474c9c8ce,5fdc271260963c60959facd73a6b555a,768b1b55a99fb5326c78479d06997b98,0bcba3f2d2e7b4080a0d510eb3d210dd,8384e0d7ae67a5ad2ace70174fb71d12,da2e8d79aa0010083b40f6a4d2f76dba,682081d4c773f1ac8e3935f3ad6f72f6,787503c8d9ba5e44f388d566b30d3849,1513afe6c5523825ba9d22cf2dd52dc1,7cb5e52706b3ff04396ac03c416cc09a,91f33c237e1db63164dfb39fb44f4c9c,4ae0f702d1e3515bbbe58f96db668098,438e9746e9b295dfe8a3685c48935f4f,7d7bb43f72075a5e171dc02dcf23780d,373d148295aa718cde37a9d93f8cca3f,7822582c202c2521fea3fd667c436a31,d0a25d8c07e95d646d21bec9d51577fa,a6ebd6850f5ced07f5ce1f811a44831c,e1529479c46d63b7947586c7a37ba709,28b4c5d2aad07665bce904a681cbfdd4,3c60cbdc4dd48e2a5b08e7d9de4865c5,47d792ef5e5d855f89c030da011a799b,575088c5a9a867b44a5f854105399a33,924fe5dc830391b398ff7b9fc2d8bd22,8f3239045b94d86ba67cd4a7f53d0bae,608881546380d8db17664576d17a2482,49e326fe0f8d8d4e27312e547b6b414f,7fa1cdc645f02745f6fb26abe312e75e,9c9b688f26e5a3b3b44eb0f5336814f4,43580384cba6f832d8871d649d923501,d8f5a31f10a8fe7db09536973ec42348,bf17d5137c336dc16b046fa190c5351f,d47234667a61f8d7f354caf1c0fdf2ae,12a0e07c4646558ca0e39445bae26427,9d54c899562ad34810f0c2118a0fff42,2086857163b30bf27a8311ca587e8939,5fd168200f4a61084cb520b65391233c,ace9bd022e0ffd6415788fae898bd5d0,36461bb4f9ef83927d1626224cfb8c48,e8a0e2482fd99a2898e9d7e3f6c698da,fd849b2a094720de035c6645665938cd,e6c0b9a6aecd73a81379140cb953995e,bddbf4148d3c48a87349acbb8f048c8d,ee659a7a8a8168f1cd8b768f6eb3a784,2a526341ae388b9a485a392b293e25cb,351fc8c9957d07c225622497a4ae8135,846f9429cc2b163fd4c6016cc4804887,7acab543a4c8952784ef552794aa3396 -->
<!-- werkrevisor-folded -->
<details><summary>🟡 werkrevisor YELLOW for <code>e716ea6</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6391">the result for <code>b232092</code></a></summary>
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** possible secrets in added lines: tests/test_prlens.py:104 (private_key), tests/test_prlens.py:123 (private_key)
- **YELLOW** changed files not judged by Jev (possible secrets in the diff): .dockerignore, Dockerfile, statistics/build.gradle.kts and 14 more
- **hint** the PR document was not compared with the diff: possible secrets in the diff
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM skipped (possible secrets in the diff), duration 2.1 s, no model call, cost 0 USD, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).<br>
Reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
</sub>
</details>
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
[high] Generate diagrams from the diff that passed the secret scan (Codex review)
This fetches the live PR diff again, while may_draw reflects the earlier diff's secret scan. A push between publication and this fetch can therefore send newly added secrets to OpenRouter and attach diagrams of the new head to the old head's result. Reproduced by changing the fake PR head and diff during set_status: the drawing callback received a private-key marker despite no secrets reason. Reuse the scanned diff instead of fetching it again.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Generate diagrams from the diff that passed the secret scan** (Codex review)
This fetches the live PR diff again, while may_draw reflects the earlier diff's secret scan. A push between publication and this fetch can therefore send newly added secrets to OpenRouter and attach diagrams of the new head to the old head's result. Reproduced by changing the fake PR head and diff during set_status: the drawing callback received a private-key marker despite no secrets reason. Reuse the scanned diff instead of fetching it again.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in a1cb668: the review keeps the diff that the rules and the secret scan saw (result.scanned_diff); _attach_diagrams draws only from it and never fetches the diff again. Scenario#121.07, red/green: test_pr_lens_gets_the_diff_that_passed_the_secret_scan got the later diff before the fix.
Fixed in `a1cb668`: the review keeps the diff that the rules and the secret scan saw (`result.scanned_diff`); `_attach_diagrams` draws only from it and never fetches the diff again. Scenario#121.07, red/green: `test_pr_lens_gets_the_diff_that_passed_the_secret_scan` got the later diff before the fix.
The change adds an external model data path and third-party code inside the credential-bearing review process. Mistakes can disclose repository secrets beyond what the mocked tests verify.
Findings
[high] Generate diagrams from the diff that passed the secret scan at werkrevisor/cli.py:1266, 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 486649 (cached 414848) / out 2108, 69.6 s, 12 commands; reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9`.
<!-- werkrevisor-codex:e716ea6c87a9d90eac9e4930551ab6278fb43fc9 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
<!-- werkrevisor-folded -->
<details><summary>⚠️ werkrevisor ERROR for <code>?</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6391">the result for <code>b232092</code></a></summary>
## Codex review: critical
The change adds an external model data path and third-party code inside the credential-bearing review process. Mistakes can disclose repository secrets beyond what the mocked tests verify.
### Findings
1. **[high] Generate diagrams from the diff that passed the secret scan** at `werkrevisor/cli.py:1266`, 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 486649 (cached 414848) / out 2108, 69.6 s, 12 commands; reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9`.
</sub>
</details>
ORANGE 1 finding(s) that Jev rates as probably real and severe: werkrevisor/config.py:715-723
YELLOW risky build changes according to Jev: .dockerignore (weakens checks 0.11, risk 1.52, security 0.02), Dockerfile (weakens checks 0.10, risk 1.89, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
hint 12 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.01)
hint 24 changed file(s) agree with the PR document according to Jev
hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
hint 1 changed file was given to the AI only as diff, not in full, so it could not check it against the rest of its file (all full files together would exceed [review] max_full_files_chars = 160000, and no excerpt fits the limits either): werkrevisor/prlens.py (advisory: Jev judged every changed file)
hint files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
Findings
Missing upper bound on max_diagrams at werkrevisor/config.py:715-723, severity unknown, counted as medium, ORANGE, as a line comment
Classifier
16 of 16 units passed all questions (1 PR document(s)).
5 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 78245, calls 1, tokens in 75484 / out 20849 (reasoning included in out), duration 222.0 s, cost 0.0476 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13722, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1845, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 26682 / out 477, cost 0.0036 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 119752, cost 0.0050 USD, build file judge `jev-1.13.0` calls 17, tokens in 20141, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 1.0 s, doc_check 1.6 s, context 9.0 s, model_review 207.8 s, finding_judge 0.8 s, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).
Reviewed head `b232092301d0712bc541e40230fc12efb4b91625` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
<!-- werkrevisor:b232092301d0712bc541e40230fc12efb4b91625 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:6a5dd6d15a75ce527b81c68c2818c813,d08f070eb191140febbed9f8337e84c4,36931004656593df9fa3e3ebc963e9d2,358dfaf22bbde637138d66e4086d5817,fd005bda47e317b42d39a976c2a11daf,cfb5b10cb3cf703bf6ed41383d265d22,23c03ab2929fa10aa09d24ae9bce8090,97ff1748d79afbd3818e3a037f781eeb,db20165e1d03111a86c2c21f791b17ff,c4a55b1253ce650869e43668f1ca33a8,86b61de5e5dd9a3913e228b031e6b815,c7426376be99af7fb99445a20381c4e3,4e68f592885c14cffac308c67e33a1cf,83cf952851e2a6f8031616af674d1a53,5bdab77a421047471ebd4aece905c38c,03196a062679ab178fd54ab43daf0474,61f9f80cd1e1fcda02b28d6474c9c8ce,5fdc271260963c60959facd73a6b555a,768b1b55a99fb5326c78479d06997b98,0bcba3f2d2e7b4080a0d510eb3d210dd,8384e0d7ae67a5ad2ace70174fb71d12,da2e8d79aa0010083b40f6a4d2f76dba,f26f2da88bcabc9ef9b37f1400358186,787503c8d9ba5e44f388d566b30d3849,1513afe6c5523825ba9d22cf2dd52dc1,7cb5e52706b3ff04396ac03c416cc09a,91f33c237e1db63164dfb39fb44f4c9c,4ae0f702d1e3515bbbe58f96db668098,438e9746e9b295dfe8a3685c48935f4f,7d7bb43f72075a5e171dc02dcf23780d,373d148295aa718cde37a9d93f8cca3f,7822582c202c2521fea3fd667c436a31,d0a25d8c07e95d646d21bec9d51577fa,a6ebd6850f5ced07f5ce1f811a44831c,e1529479c46d63b7947586c7a37ba709,28b4c5d2aad07665bce904a681cbfdd4,3c60cbdc4dd48e2a5b08e7d9de4865c5,47d792ef5e5d855f89c030da011a799b,575088c5a9a867b44a5f854105399a33,924fe5dc830391b398ff7b9fc2d8bd22,8f3239045b94d86ba67cd4a7f53d0bae,608881546380d8db17664576d17a2482,49e326fe0f8d8d4e27312e547b6b414f,7fa1cdc645f02745f6fb26abe312e75e,9c9b688f26e5a3b3b44eb0f5336814f4,43580384cba6f832d8871d649d923501,d8f5a31f10a8fe7db09536973ec42348,bf17d5137c336dc16b046fa190c5351f,d47234667a61f8d7f354caf1c0fdf2ae,12a0e07c4646558ca0e39445bae26427,9d54c899562ad34810f0c2118a0fff42,2086857163b30bf27a8311ca587e8939,5fd168200f4a61084cb520b65391233c,ace9bd022e0ffd6415788fae898bd5d0,36461bb4f9ef83927d1626224cfb8c48,e8a0e2482fd99a2898e9d7e3f6c698da,fd849b2a094720de035c6645665938cd,e6c0b9a6aecd73a81379140cb953995e,bddbf4148d3c48a87349acbb8f048c8d,ee659a7a8a8168f1cd8b768f6eb3a784,2a526341ae388b9a485a392b293e25cb,351fc8c9957d07c225622497a4ae8135,846f9429cc2b163fd4c6016cc4804887,7acab543a4c8952784ef552794aa3396 -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>b232092</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6404">the result for <code>a1cb668</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/config.py:715-723
- **YELLOW** risky build changes according to Jev: .dockerignore (weakens checks 0.11, risk 1.52, security 0.02), Dockerfile (weakens checks 0.10, risk 1.89, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
- **hint** 12 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.01)
- **hint** 24 changed file(s) agree with the PR document according to Jev
- **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
- **hint** 1 changed file was given to the AI only as diff, not in full, so it could not check it against the rest of its file (all full files together would exceed [review] max_full_files_chars = 160000, and no excerpt fits the limits either): werkrevisor/prlens.py (advisory: Jev judged every changed file)
- **hint** files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
### Findings
1. **Missing upper bound on max_diagrams** at `werkrevisor/config.py:715-723`, severity unknown, counted as medium, ORANGE, as a line comment
### Classifier
16 of 16 units passed all questions (1 PR document(s)).
5 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 78245, calls 1, tokens in 75484 / out 20849 (reasoning included in out), duration 222.0 s, cost 0.0476 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13722, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1845, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 26682 / out 477, cost 0.0036 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 119752, cost 0.0050 USD, build file judge `jev-1.13.0` calls 17, tokens in 20141, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 1.0 s, doc_check 1.6 s, context 9.0 s, model_review 207.8 s, finding_judge 0.8 s, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).<br>
Reviewed head `b232092301d0712bc541e40230fc12efb4b91625` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for b232092301d0712bc541e40230fc12efb4b91625.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `b232092301d0712bc541e40230fc12efb4b91625`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:b232092301d0712bc541e40230fc12efb4b91625 -->
Missing upper bound on max_diagrams, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.82, severity 3.0 of 3
_validate_diagrams only checks that max_diagrams is a positive integer, but does not enforce the upper bound of 5 mentioned in both the config docstring and the README ("Gitea takes at most 5 attachments per comment by default"). If an operator sets max_diagrams above 5, PR Lens can produce more SVGs than Gitea accepts and the upload fails at runtime; _attach_diagrams catches the error and only logs one redacted line, leaving the diagrams missing without the operator knowing why.
**Missing upper bound on max_diagrams**, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.82, severity 3.0 of 3
`_validate_diagrams` only checks that `max_diagrams` is a positive integer, but does not enforce the upper bound of 5 mentioned in both the config docstring and the README ("Gitea takes at most 5 attachments per comment by default"). If an operator sets `max_diagrams` above 5, PR Lens can produce more SVGs than Gitea accepts and the upload fails at runtime; `_attach_diagrams` catches the error and only logs one redacted line, leaving the diagrams missing without the operator knowing why.
Fixed in a1cb668, without a hard cap at 5: MAX_FILES is a setting of each Gitea instance. An upload that Gitea refuses ends the uploads; the comment links the diagrams that Gitea took, and the log names how many were left out and the limit. Scenario#121.06, red/green: test_diagrams_beyond_the_attachment_limit_of_gitea_are_left_out failed before the fix.
Fixed in `a1cb668`, without a hard cap at 5: `MAX_FILES` is a setting of each Gitea instance. An upload that Gitea refuses ends the uploads; the comment links the diagrams that Gitea took, and the log names how many were left out and the limit. Scenario#121.06, red/green: `test_diagrams_beyond_the_attachment_limit_of_gitea_are_left_out` failed before the fix.
[high] Refetching the live diff bypasses the earlier secret scan (Codex review)
The secret veto checks the diff read during _review, but diagram generation fetches the current PR diff again after publication without rescanning it or checking its head. If a push adds a secret between those requests, the new secret is sent to OpenRouter under the earlier head's metadata. An in-memory reproduction confirmed this while the result remained GREEN. Pass the already-scanned diff to diagram generation.
Fix it, or reply why it does not hold, and resolve this comment.
**[high] Refetching the live diff bypasses the earlier secret scan** (Codex review)
The secret veto checks the diff read during _review, but diagram generation fetches the current PR diff again after publication without rescanning it or checking its head. If a push adds a secret between those requests, the new secret is sent to OpenRouter under the earlier head's metadata. An in-memory reproduction confirmed this while the result remained GREEN. Pass the already-scanned diff to diagram generation.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Fixed in a1cb668, as in the same finding on e716ea6: PR Lens gets only the diff that the review scanned (result.scanned_diff); _attach_diagrams never fetches it again. Scenario#121.07, with red/green.
Fixed in `a1cb668`, as in the same finding on `e716ea6`: PR Lens gets only the diff that the review scanned (`result.scanned_diff`); `_attach_diagrams` never fetches it again. Scenario#121.07, with red/green.
The change adds third-party runtime code to the credential-bearing review process and a new route for sending PR diffs to an external model. Mistakes in secret handling or isolation can disclose sensitive data beyond what the mocked tests verify.
Findings
[high] Refetching the live diff bypasses the earlier secret scan at werkrevisor/cli.py:1266, 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 536360 (cached 476672) / out 2304, 78.1 s, 16 commands; reviewed head `b232092301d0712bc541e40230fc12efb4b91625`.
<!-- werkrevisor-codex:b232092301d0712bc541e40230fc12efb4b91625 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
<!-- werkrevisor-folded -->
<details><summary>⚠️ werkrevisor ERROR for <code>?</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/121#issuecomment-6404">the result for <code>a1cb668</code></a></summary>
## Codex review: critical
The change adds third-party runtime code to the credential-bearing review process and a new route for sending PR diffs to an external model. Mistakes in secret handling or isolation can disclose sensitive data beyond what the mocked tests verify.
### Findings
1. **[high] Refetching the live diff bypasses the earlier secret scan** at `werkrevisor/cli.py:1266`, 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 536360 (cached 476672) / out 2304, 78.1 s, 16 commands; reviewed head `b232092301d0712bc541e40230fc12efb4b91625`.
</sub>
</details>
YELLOW risky build changes according to Jev: .dockerignore (weakens checks 0.11, risk 1.55, security 0.02), Dockerfile (weakens checks 0.10, risk 1.89, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
hint 13 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.01)
hint 25 changed file(s) agree with the PR document according to Jev
hint 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
hint 3 changed files were given to the AI only as diff, not in full, so it could not check them against the rest of their file (all full files together would exceed [review] max_full_files_chars = 160000, and no excerpt fits the limits either): werkrevisor/pr_lens.mjs, werkrevisor/prlens.py, werkrevisor/report.py (advisory: Jev judged every changed file)
hint files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
Classifier
16 of 16 units passed all questions (1 PR document(s)).
5 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 80033, calls 1, tokens in 77193 / out 28781 (reasoning included in out), duration 325.9 s, cost 0.0577 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13926, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 4, tokens in 36001 / out 1049, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 25, tokens in 130877, cost 0.0055 USD, build file judge `jev-1.13.0` calls 18, tokens in 21328, cost 0.0009 USD, phases: path_judge 1.3 s, classifier 1.0 s, doc_check 1.7 s, context 19.8 s, model_review 301.3 s, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).
Reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
<!-- werkrevisor:a1cb668dc4434beff137a30b342d80223e2c7252 -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:6a5dd6d15a75ce527b81c68c2818c813,d08f070eb191140febbed9f8337e84c4,36931004656593df9fa3e3ebc963e9d2,358dfaf22bbde637138d66e4086d5817,fd005bda47e317b42d39a976c2a11daf,cfb5b10cb3cf703bf6ed41383d265d22,23c03ab2929fa10aa09d24ae9bce8090,97ff1748d79afbd3818e3a037f781eeb,db20165e1d03111a86c2c21f791b17ff,c4a55b1253ce650869e43668f1ca33a8,86b61de5e5dd9a3913e228b031e6b815,c7426376be99af7fb99445a20381c4e3,27a941d5e6c8f8b226548d1b038b45f2,83cf952851e2a6f8031616af674d1a53,5bdab77a421047471ebd4aece905c38c,03196a062679ab178fd54ab43daf0474,61f9f80cd1e1fcda02b28d6474c9c8ce,5fdc271260963c60959facd73a6b555a,768b1b55a99fb5326c78479d06997b98,0bcba3f2d2e7b4080a0d510eb3d210dd,8384e0d7ae67a5ad2ace70174fb71d12,da2e8d79aa0010083b40f6a4d2f76dba,0eb9efb660d6fa04ee38f2c8ecf9b419,787503c8d9ba5e44f388d566b30d3849,1513afe6c5523825ba9d22cf2dd52dc1,7cb5e52706b3ff04396ac03c416cc09a,91f33c237e1db63164dfb39fb44f4c9c,4ae0f702d1e3515bbbe58f96db668098,438e9746e9b295dfe8a3685c48935f4f,7d7bb43f72075a5e171dc02dcf23780d,373d148295aa718cde37a9d93f8cca3f,7822582c202c2521fea3fd667c436a31,d0a25d8c07e95d646d21bec9d51577fa,a6ebd6850f5ced07f5ce1f811a44831c,e1529479c46d63b7947586c7a37ba709,28b4c5d2aad07665bce904a681cbfdd4,3c60cbdc4dd48e2a5b08e7d9de4865c5,47d792ef5e5d855f89c030da011a799b,575088c5a9a867b44a5f854105399a33,924fe5dc830391b398ff7b9fc2d8bd22,8f3239045b94d86ba67cd4a7f53d0bae,608881546380d8db17664576d17a2482,49e326fe0f8d8d4e27312e547b6b414f,7fa1cdc645f02745f6fb26abe312e75e,9c9b688f26e5a3b3b44eb0f5336814f4,181205433044243e622f2d8e9e0a9d7f,43580384cba6f832d8871d649d923501,d8f5a31f10a8fe7db09536973ec42348,ef2dd26a0d22dd31e9de9c71c24e43cb,c272aa0bbf617c63f736cc544a985f0e,12a0e07c4646558ca0e39445bae26427,9d54c899562ad34810f0c2118a0fff42,2086857163b30bf27a8311ca587e8939,5fd168200f4a61084cb520b65391233c,ace9bd022e0ffd6415788fae898bd5d0,36461bb4f9ef83927d1626224cfb8c48,e8a0e2482fd99a2898e9d7e3f6c698da,fd849b2a094720de035c6645665938cd,e6c0b9a6aecd73a81379140cb953995e,bddbf4148d3c48a87349acbb8f048c8d,ee659a7a8a8168f1cd8b768f6eb3a784,2a526341ae388b9a485a392b293e25cb,351fc8c9957d07c225622497a4ae8135,846f9429cc2b163fd4c6016cc4804887,7acab543a4c8952784ef552794aa3396,720d305fea067e7778f51287b7e43d99 -->
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** risky build changes according to Jev: .dockerignore (weakens checks 0.11, risk 1.55, security 0.02), Dockerfile (weakens checks 0.10, risk 1.89, security 0.04), tools/build-rootfs (weakens checks 0.05, risk 2.00, security 0.02) and 1 more
- **hint** 13 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.01)
- **hint** 25 changed file(s) agree with the PR document according to Jev
- **hint** 1 changed file was given to the AI as excerpt of the selected lines and 5 lines around each changed line, not in full (each larger than [review] max_full_file_chars = 80000): werkrevisor/cli.py
- **hint** 3 changed files were given to the AI only as diff, not in full, so it could not check them against the rest of their file (all full files together would exceed [review] max_full_files_chars = 160000, and no excerpt fits the limits either): werkrevisor/pr_lens.mjs, werkrevisor/prlens.py, werkrevisor/report.py (advisory: Jev judged every changed file)
- **hint** files the model cannot review: docs/werkrevisor-review-inside-dark.svg, docs/werkrevisor-review-inside.svg, tools/pr-lens/package-lock.json (advisory: Jev judged every changed file)
### Classifier
16 of 16 units passed all questions (1 PR document(s)).
5 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 80033, calls 1, tokens in 77193 / out 28781 (reasoning included in out), duration 325.9 s, cost 0.0577 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13926, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 4, tokens in 36001 / out 1049, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 25, tokens in 130877, cost 0.0055 USD, build file judge `jev-1.13.0` calls 18, tokens in 21328, cost 0.0009 USD, phases: path_judge 1.3 s, classifier 1.0 s, doc_check 1.7 s, context 19.8 s, model_review 301.3 s, config: defaults + host + repository (.werkrevisor.toml at main a6185f0).<br>
Reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
</sub>
mi
merged commit db2fba45e7 into main2026-10-18 20:57:16 +02:00
mi
deleted branch claude-code/pr-lens-diagrams2026-10-18 20:57:16 +02:00
The comment body is read before diagram generation and written back afterward. If a newer head finishes review meanwhile, _fold_earlier marks this comment as superseded, but this write restores the stale body and removes that notice and link. This was reproduced using the real folding and attachment functions. Re-read and preserve the current comment body after drawing.
Fix it, or reply why it does not hold, and resolve this comment.
**[medium] Diagram attachment overwrites concurrent comment updates** (Codex review)
The comment body is read before diagram generation and written back afterward. If a newer head finishes review meanwhile, _fold_earlier marks this comment as superseded, but this write restores the stale body and removes that notice and link. This was reproduced using the real folding and attachment functions. Re-read and preserve the current comment body after drawing.
Fix it, or reply why it does not hold, and resolve this comment.
<!-- werkrevisor-codex -->
Holds; PR#121 was merged a minute before this comment. Fixed in PR#127 (786ca61): _attach_diagrams reads the body again after the drawing and puts the diagrams inside a fold, so the fold and its link stay. Scenario#127.01, red/green.
Holds; PR#121 was merged a minute before this comment. Fixed in PR#127 (`786ca61`): `_attach_diagrams` reads the body again after the drawing and puts the diagrams inside a fold, so the fold and its link stay. Scenario#127.01, red/green.
The change introduces third-party executable code into the credential-bearing review process and a new outbound path for PR diffs. Mistakes at this boundary could expose credentials or private code beyond what the mocked tests verify.
Findings
[medium] Diagram attachment overwrites concurrent comment updates at werkrevisor/cli.py:1281, 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 556495 (cached 484352) / out 3126, 104.1 s, 14 commands; reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252`.
<!-- werkrevisor-codex:a1cb668dc4434beff137a30b342d80223e2c7252 -->
<!-- werkrevisor-codex-critical:true -->
<!-- werkrevisor-codex-unattached:0 -->
<!-- werkrevisor-codex -->
## Codex review: critical
The change introduces third-party executable code into the credential-bearing review process and a new outbound path for PR diffs. Mistakes at this boundary could expose credentials or private code beyond what the mocked tests verify.
### Findings
1. **[medium] Diagram attachment overwrites concurrent comment updates** at `werkrevisor/cli.py:1281`, 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 556495 (cached 484352) / out 3126, 104.1 s, 14 commands; reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252`.
</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.
See docs/prs for the PR document.
🤖 Generated with Claude Code
WIP: diagrams of PR Lens in the review commentto werkrevisor 0.50.0: diagrams of PR Lens in the result comment926e2f8461tobabb25ace2🟡 werkrevisor YELLOW for
babb25a, superseded by the result for34a7b98🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Classifier
13 of 14 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 77528, calls 1, tokens in 74786 / out 30589 (reasoning included in out), duration 157.0 s, cost 0.0591 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11829, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 23759 / out 326, cost 0.0031 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 109086, cost 0.0046 USD, build file judge `jev-1.13.0` calls 17, tokens in 19726, cost 0.0008 USD, phases: path_judge 1.3 s, classifier 1.0 s, doc_check 1.6 s, context 6.9 s, model_review 145.6 s, config: defaults + host + repository (.werkrevisor.toml at main3 answers ignored because of a confidence below [classifier] min_confidence.
4685c8d).Reviewed head `babb25ace2f60d9b44f0def5a2f3aa2233c60db2` against base `4685c8db840b552add7486260d5a6f0ed7ee9d35`, werkrevisor 0.49.1.
Codex review of
babb25ace2f60d9b44f0def5a2f3aa2233c60db2@@ -1118,6 +1121,8 @@ def execute(config, pr, deps, redactor, publish=True, use_llm=True, config_sourcif outcome.superseded or result.verdict is Verdict.ERROR:result.exit_code = Verdict.ERROR.exit_codeelif outcome.published and config.diagrams.enabled and deps.draw_diagrams is not None:[medium] Diagram generation ignores --no-llm (Codex review)
This condition does not check use_llm. With diagrams enabled and an OpenRouter key available, --no-llm still invokes the diagram model, transmitting the diff and incurring charges despite requesting deterministic rules only. Reproduced with use_llm=False: the review reports 'skipped (--no-llm)' but draw_diagrams is called.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
e716ea6: drawing needsuse_llm. Scenario#121.08, red/green:test_no_llm_draws_no_diagramsfailed before the fix.@@ -1245,0 +1259,4 @@# A rerun on the same head finds the diagrams of the first run and draws no new ones.assets = prlens.own_assets(gitea.list_comment_assets(comment["id"]))if not assets:drawn = deps.draw_diagrams(config, pr, gitea.get_pr_diff(pr.number))[high] Diagram generation bypasses the secret-scan veto (Codex review)
When the secret scan detects credentials, the review finishes YELLOW and skips its model calls. Diagram generation still runs and forwards the raw diff to OpenRouter. An in-memory reproduction confirmed that a diff containing a detected password reaches draw_diagrams unchanged, defeating the existing protection against spreading leaked secrets.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
e716ea6: only a fresh review without asecretsreason may draw; a rerun only links SVGs that are attached already, since it does not know whether its first run found a secret. Scenario#121.07, red/green:test_a_possible_secret_keeps_the_diff_from_pr_lensfailed before the fix.⚠️ werkrevisor ERROR for
?, superseded by the result for34a7b98Codex review: critical
The change adds third-party code and a new outbound model-call path inside the credential-bearing review process. Mistakes can disclose secrets, and the mocked tests do not cover this security boundary.
Findings
werkrevisor/cli.py:1262, as a line commentwerkrevisor/cli.py:1124, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 373526 (cached 301952) / out 2533, 80.2 s, 14 commands; reviewed head `babb25ace2f60d9b44f0def5a2f3aa2233c60db2`.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 YELLOW for
34a7b98, superseded by the result fora33b894🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Classifier
13 of 14 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 78437, calls 1, tokens in 75672 / out 25615 (reasoning included in out), duration 262.1 s, cost 0.0534 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11807, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 23759 / out 348, cost 0.0004 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 108822, cost 0.0046 USD, build file judge `jev-1.13.0` calls 17, tokens in 19726, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 0.9 s, doc_check 1.5 s, context 6.3 s, model_review 251.7 s, config: defaults + host + repository (.werkrevisor.toml at main3 answers ignored because of a confidence below [classifier] min_confidence.
4685c8d).Reviewed head `34a7b988c371bef08b776aedd0ad095cdafcff6d` against base `4685c8db840b552add7486260d5a6f0ed7ee9d35`, werkrevisor 0.49.1.
🟡 werkrevisor YELLOW for
a33b894, superseded by the result fore716ea6🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Gate: no human review requested; merge conflict with main: the author rebases the branch onto main and pushes.
Change kind:
mixed.Reasons
Classifier
14 of 14 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 77519, calls 1, tokens in 74781 / out 18890 (reasoning included in out), duration 206.4 s, cost 0.0451 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11815, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 23759 / out 493, cost 0.0005 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 108918, cost 0.0046 USD, build file judge `jev-1.13.0` calls 17, tokens in 19726, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 0.9 s, doc_check 1.6 s, context 8.4 s, model_review 193.7 s, config: defaults + host + repository (.werkrevisor.toml at main3 answers ignored because of a confidence below [classifier] min_confidence.
4685c8d).Reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f` against base `4685c8db840b552add7486260d5a6f0ed7ee9d35`, werkrevisor 0.49.1.
Codex review of
a33b894edda3b4e015e49c8824b5e9d5e701516f@@ -1118,6 +1121,8 @@ def execute(config, pr, deps, redactor, publish=True, use_llm=True, config_sourcif outcome.superseded or result.verdict is Verdict.ERROR:result.exit_code = Verdict.ERROR.exit_codeelif outcome.published and config.diagrams.enabled and deps.draw_diagrams is not None:[medium] Diagram generation ignores --no-llm (Codex review)
This condition does not check use_llm. With diagrams enabled and publishing allowed, --no-llm still invokes PR Lens and its external model, transmitting the diff and incurring charges despite the request to apply deterministic rules only. Reproduced with use_llm=False.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
e716ea6, as in the same finding onbabb25a: drawing needsuse_llm, a fresh review and nosecretsreason (Scenario#121.07, Scenario#121.08, each with red/green).@@ -1245,0 +1259,4 @@# A rerun on the same head finds the diagrams of the first run and draws no new ones.assets = prlens.own_assets(gitea.list_comment_assets(comment["id"]))if not assets:drawn = deps.draw_diagrams(config, pr, gitea.get_pr_diff(pr.number))[high] Diagram generation bypasses the secret-scan guard (Codex review)
With diagrams enabled, a diff flagged by the secret scanner produces YELLOW and skips the review model, but still reaches this call unchanged and is sent to OpenRouter. Reproduced with a private-key marker: the review model received zero calls while the diagram generator received the raw diff. This defeats the existing protection against sending detected secrets to external models.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
e716ea6, as in the same finding onbabb25a: drawing needsuse_llm, a fresh review and nosecretsreason (Scenario#121.07, Scenario#121.08, each with red/green).⚠️ werkrevisor ERROR for
?, superseded by the result fore716ea6Codex review: critical
The change introduces third-party Node.js code into the credential-bearing review process and a new path that sends PR contents to an external model. Mistakes can expose secrets, which the mocked tests do not establish protection against.
Findings
werkrevisor/cli.py:1262, as a line commentwerkrevisor/cli.py:1124, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 466369 (cached 392192) / out 2579, 71.9 s, 16 commands; reviewed head `a33b894edda3b4e015e49c8824b5e9d5e701516f`.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 0.50.0: diagrams of PR Lens in the result commentto werkrevisor 0.52.0: diagrams of PR Lens in the result commenta33b894eddtoe716ea6c87🟡 werkrevisor YELLOW for
e716ea6, superseded by the result forb232092🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
- YELLOW possible secrets in added lines: tests/test_prlens.py:104 (private_key), tests/test_prlens.py:123 (private_key)
- YELLOW changed files not judged by Jev (possible secrets in the diff): .dockerignore, Dockerfile, statistics/build.gradle.kts and 14 more
- hint the PR document was not compared with the diff: possible secrets in the diff
Usage: model `openrouter/minimax/minimax-m3`, LLM skipped (possible secrets in the diff), duration 2.1 s, no model call, cost 0 USD, config: defaults + host + repository (.werkrevisor.toml at maina6185f0).Reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
Codex review of
e716ea6c87a9d90eac9e4930551ab6278fb43fc9@@ -1245,0 +1263,4 @@if not assets:if not may_draw:returndrawn = deps.draw_diagrams(config, pr, gitea.get_pr_diff(pr.number))[high] Generate diagrams from the diff that passed the secret scan (Codex review)
This fetches the live PR diff again, while may_draw reflects the earlier diff's secret scan. A push between publication and this fetch can therefore send newly added secrets to OpenRouter and attach diagrams of the new head to the old head's result. Reproduced by changing the fake PR head and diff during set_status: the drawing callback received a private-key marker despite no secrets reason. Reuse the scanned diff instead of fetching it again.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
a1cb668: the review keeps the diff that the rules and the secret scan saw (result.scanned_diff);_attach_diagramsdraws only from it and never fetches the diff again. Scenario#121.07, red/green:test_pr_lens_gets_the_diff_that_passed_the_secret_scangot the later diff before the fix.⚠️ werkrevisor ERROR for
?, superseded by the result forb232092Codex review: critical
The change adds an external model data path and third-party code inside the credential-bearing review process. Mistakes can disclose repository secrets beyond what the mocked tests verify.
Findings
werkrevisor/cli.py:1266, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 486649 (cached 414848) / out 2108, 69.6 s, 12 commands; reviewed head `e716ea6c87a9d90eac9e4930551ab6278fb43fc9`.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
b232092, superseded by the result fora1cb668🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
werkrevisor/config.py:715-723, severity unknown, counted as medium, ORANGE, as a line commentClassifier
16 of 16 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 78245, calls 1, tokens in 75484 / out 20849 (reasoning included in out), duration 222.0 s, cost 0.0476 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13722, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1845, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 26682 / out 477, cost 0.0036 USD (reported), PR document check `jev-1.13.0` calls 24, tokens in 119752, cost 0.0050 USD, build file judge `jev-1.13.0` calls 17, tokens in 20141, cost 0.0008 USD, phases: path_judge 1.1 s, classifier 1.0 s, doc_check 1.6 s, context 9.0 s, model_review 207.8 s, finding_judge 0.8 s, config: defaults + host + repository (.werkrevisor.toml at main5 answers ignored because of a confidence below [classifier] min_confidence.
a6185f0).Reviewed head `b232092301d0712bc541e40230fc12efb4b91625` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
werkrevisor: ORANGE / FINDINGS for
b232092301d0712bc541e40230fc12efb4b91625.The result comment of werkrevisor holds the details.
@@ -689,6 +712,17 @@ def _validate_doc_check(config):raise ConfigError("[doc_check] hint_min must not be above orange_min")def _validate_diagrams(d, review_model_id):Missing upper bound on max_diagrams, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.82, severity 3.0 of 3
_validate_diagramsonly checks thatmax_diagramsis a positive integer, but does not enforce the upper bound of 5 mentioned in both the config docstring and the README ("Gitea takes at most 5 attachments per comment by default"). If an operator setsmax_diagramsabove 5, PR Lens can produce more SVGs than Gitea accepts and the upload fails at runtime;_attach_diagramscatches the error and only logs one redacted line, leaving the diagrams missing without the operator knowing why.Fixed in
a1cb668, without a hard cap at 5:MAX_FILESis a setting of each Gitea instance. An upload that Gitea refuses ends the uploads; the comment links the diagrams that Gitea took, and the log names how many were left out and the limit. Scenario#121.06, red/green:test_diagrams_beyond_the_attachment_limit_of_gitea_are_left_outfailed before the fix.Codex review of
b232092301d0712bc541e40230fc12efb4b91625@@ -1245,0 +1263,4 @@if not assets:if not may_draw:returndrawn = deps.draw_diagrams(config, pr, gitea.get_pr_diff(pr.number))[high] Refetching the live diff bypasses the earlier secret scan (Codex review)
The secret veto checks the diff read during _review, but diagram generation fetches the current PR diff again after publication without rescanning it or checking its head. If a push adds a secret between those requests, the new secret is sent to OpenRouter under the earlier head's metadata. An in-memory reproduction confirmed this while the result remained GREEN. Pass the already-scanned diff to diagram generation.
Fix it, or reply why it does not hold, and resolve this comment.
Fixed in
a1cb668, as in the same finding one716ea6: PR Lens gets only the diff that the review scanned (result.scanned_diff);_attach_diagramsnever fetches it again. Scenario#121.07, with red/green.⚠️ werkrevisor ERROR for
?, superseded by the result fora1cb668Codex review: critical
The change adds third-party runtime code to the credential-bearing review process and a new route for sending PR diffs to an external model. Mistakes in secret handling or isolation can disclose sensitive data beyond what the mocked tests verify.
Findings
werkrevisor/cli.py:1266, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 536360 (cached 476672) / out 2304, 78.1 s, 16 commands; reviewed head `b232092301d0712bc541e40230fc12efb4b91625`.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: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Classifier
16 of 16 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 80033, calls 1, tokens in 77193 / out 28781 (reasoning included in out), duration 325.9 s, cost 0.0577 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13926, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 4, tokens in 36001 / out 1049, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 25, tokens in 130877, cost 0.0055 USD, build file judge `jev-1.13.0` calls 18, tokens in 21328, cost 0.0009 USD, phases: path_judge 1.3 s, classifier 1.0 s, doc_check 1.7 s, context 19.8 s, model_review 301.3 s, config: defaults + host + repository (.werkrevisor.toml at main5 answers ignored because of a confidence below [classifier] min_confidence.
a6185f0).Reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252` against base `a6185f094958d55dd8c59118a8413ad13d8c198a`, werkrevisor 0.51.0.
Codex review of
a1cb668dc4434beff137a30b342d80223e2c7252@@ -1245,0 +1278,4 @@file=sys.stderr)breakif assets:gitea.edit_issue_comment(comment["id"], body + prlens.section(assets))[medium] Diagram attachment overwrites concurrent comment updates (Codex review)
The comment body is read before diagram generation and written back afterward. If a newer head finishes review meanwhile, _fold_earlier marks this comment as superseded, but this write restores the stale body and removes that notice and link. This was reproduced using the real folding and attachment functions. Re-read and preserve the current comment body after drawing.
Fix it, or reply why it does not hold, and resolve this comment.
Holds; PR#121 was merged a minute before this comment. Fixed in PR#127 (
786ca61):_attach_diagramsreads the body again after the drawing and puts the diagrams inside a fold, so the fold and its link stay. Scenario#127.01, red/green.Codex review: critical
The change introduces third-party executable code into the credential-bearing review process and a new outbound path for PR diffs. Mistakes at this boundary could expose credentials or private code beyond what the mocked tests verify.
Findings
werkrevisor/cli.py:1281, as a line commentThe merge waits for the status
Model `gpt-6-astra`, effort high, tokens in 556495 (cached 484352) / out 3126, 104.1 s, 14 commands; reviewed head `a1cb668dc4434beff137a30b342d80223e2c7252`.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.