Design and implementation of #model.codex.gate: a runner on the workstation reviews PRs with the Codex CLI after werkrevisor.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
YELLOW PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 16 changed file(s) that neither weaken the checks nor touch security 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 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:39-45
hint model recommends merge with caution
Findings
[low] Doc-code mismatch on WIP pending status at docs/prs/2026-10-11-PR#88-codex-runner.md:39-45, hint, as a line comment
werkrevisor: YELLOW / HUMAN_REVIEW for 659d8736955db01cd56bb146ee256e02ec8260db.
The result comment of werkrevisor holds the details.
werkrevisor: YELLOW / HUMAN_REVIEW for `659d8736955db01cd56bb146ee256e02ec8260db`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:659d8736955db01cd56bb146ee256e02ec8260db -->
[low] Doc-code mismatch on WIP pending status (werkrevisor)
hint
Scenario#88.02 states that in gate mode the status ai-review/codex becomes "pending" both for a WIP PR and for a PR without a werkrevisor result. In the implementation, run_repository skips WIP PRs with continue and sets no status at all; the "waiting for the Codex review" pending status is only emitted from run_pr for non-WIP PRs that have no werkrevisor result. The test test_a_pr_waits_for_werkrevisor_and_its_wip_end only asserts runs == 0 for the WIP sub-case, never the status, so the contradiction is uncovered.
**[low] Doc-code mismatch on WIP pending status** (werkrevisor)
hint
Scenario#88.02 states that in `gate` mode the status `ai-review/codex` becomes "pending" both for a WIP PR and for a PR without a werkrevisor result. In the implementation, `run_repository` skips WIP PRs with `continue` and sets no status at all; the "waiting for the Codex review" pending status is only emitted from `run_pr` for non-WIP PRs that have no werkrevisor result. The test `test_a_pr_waits_for_werkrevisor_and_its_wip_end` only asserts `runs == 0` for the WIP sub-case, never the status, so the contradiction is uncovered.
Fixed in af6613e: a WIP PR gets no status at all; only a PR without "WIP: " and without a result of werkrevisor gets pending in gate mode, as run_pr does.
Fixed in `af6613e`: a WIP PR gets no status at all; only a PR without "WIP: " and without a result of werkrevisor gets `pending` in `gate` mode, as `run_pr` does.
claude-code marked this conversation as resolved
ai-reviewer
scheduled this pull request to auto merge when all checks succeed 2026-10-11 20:56:14 +02:00
ai-reviewer
requested review from mi 2026-10-11 20:56:14 +02:00
YELLOW PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 16 changed file(s) that neither weaken the checks nor touch security 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 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 according to Jev
hint 1 changed file was given to the AI as excerpt with 40 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/gitea.py
hint excerpt selection by openrouter/openai/gpt-6-luna failed, the fixed window was used: werkrevisor/cli.py (a range lies outside the file)
hint files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
13 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 74590, calls 1, tokens in 71502 / out 38227 (reasoning included in out), duration 396.5 s, cost 0.0673 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11874, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 527, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 3064, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 42023, cost 0.0018 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 18.3 s, doc_check 0.9 s, context 8.0 s, model_review 366.8 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `af6613e2cfff7e9010197426c4ca28d133389dd9` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:af6613e2cfff7e9010197426c4ca28d133389dd9 -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,fa447656ff15a0765e6433e0752e6f39,acfe44aa855c3119b62a7c46f5418a42,dc9178730f0b22b5e30c5cec690b5e8f,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,20887e9547a24897a4121521e049b072,b9c94dca42fbcf307ba0a4ecf63fbbeb,1f23a215ee5962d814b2b9f3cfba7b26,76a3fd6b6a10a177e4e973712e117067,9e93df245c716eda82b36ae73b956ce6,a38c07c53e226675b5d1ae0d4eb28c67,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,9ab015f9894956537a2a6036939aa887,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,2a99dc96027a4246d879d945b07c90bb,393c278aa56278e1cc97615e87089c82,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟡 werkrevisor YELLOW for <code>af6613e</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4182">the result for <code>a42e5a0</code></a></summary>
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 hard_to_read (0.59 > yellow_above = 0.5)
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 given_when_then_misused (0.78 > yellow_above = 0.6)
- **hint** 16 changed file(s) that neither weaken the checks nor touch security 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** 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 according to Jev
- **hint** 1 changed file was given to the AI as excerpt with 40 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/gitea.py
- **hint** excerpt selection by openrouter/openai/gpt-6-luna failed, the fixed window was used: werkrevisor/cli.py (a range lies outside the file)
- **hint** files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | hard_to_read | 0.59 | 0.55 | YELLOW |
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | given_when_then_misused | 0.78 | – | YELLOW |
13 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 74590, calls 1, tokens in 71502 / out 38227 (reasoning included in out), duration 396.5 s, cost 0.0673 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11874, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 527, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 3064, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 42023, cost 0.0018 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 18.3 s, doc_check 0.9 s, context 8.0 s, model_review 366.8 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `af6613e2cfff7e9010197426c4ca28d133389dd9` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
</details>
YELLOW PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 16 changed file(s) that neither weaken the checks nor touch security 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 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
13 of 14 units passed all questions (1 PR document(s)).
4 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 74899, calls 1, tokens in 71801 / out 33130 (reasoning included in out), duration 227.9 s, cost 0.0613 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11886, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 267, cost 0.0003 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 2446, cost 0.0039 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 34419, cost 0.0014 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 16.1 s, doc_check 0.9 s, context 4.4 s, model_review 204.0 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `a42e5a0c478d79a993d2aad6034d32db62d7e055` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:a42e5a0c478d79a993d2aad6034d32db62d7e055 -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,fa447656ff15a0765e6433e0752e6f39,acfe44aa855c3119b62a7c46f5418a42,0f910875d87ec8e2d0afe3daec9427b7,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,20887e9547a24897a4121521e049b072,b9c94dca42fbcf307ba0a4ecf63fbbeb,1f23a215ee5962d814b2b9f3cfba7b26,76a3fd6b6a10a177e4e973712e117067,9e93df245c716eda82b36ae73b956ce6,a38c07c53e226675b5d1ae0d4eb28c67,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,9ab015f9894956537a2a6036939aa887,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,2a99dc96027a4246d879d945b07c90bb,393c278aa56278e1cc97615e87089c82,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟡 werkrevisor YELLOW for <code>a42e5a0</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4184">the result for <code>342e224</code></a></summary>
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 hard_to_read (0.54 > yellow_above = 0.5)
- **hint** 16 changed file(s) that neither weaken the checks nor touch security 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** 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | hard_to_read | 0.54 | 0.54 | YELLOW |
13 of 14 units passed all questions (1 PR document(s)).
4 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 74899, calls 1, tokens in 71801 / out 33130 (reasoning included in out), duration 227.9 s, cost 0.0613 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11886, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 267, cost 0.0003 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 2446, cost 0.0039 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 34419, cost 0.0014 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 16.1 s, doc_check 0.9 s, context 4.4 s, model_review 204.0 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `a42e5a0c478d79a993d2aad6034d32db62d7e055` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.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
ORANGE 2 finding(s) that Jev rates as probably real and severe: werkrevisor/codex.py:116-136, werkrevisor/codex.py:162-192
YELLOW PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
YELLOW model reports a security concern: Sensitive information exposure: --sandbox read-only is the only barrier between a prompt-injected Codex run and the network. The redactor only sanitises the response, so a successful injection can exfiltrate anything Codex reads (source, secrets, Gitea token leak via env) to an attacker host before any redaction happens. The auth_secrets filter also only catches strings of length 16 or more from…
hint 16 changed file(s) that neither weaken the checks nor touch security 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 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:108-119
hint model recommends merge with caution
Findings
Short secrets bypass the redactor at werkrevisor/codex.py:116-136, severity unknown, counted as medium, ORANGE, as a line comment
Sandbox does not block the network at werkrevisor/codex.py:162-192, severity unknown, counted as medium, ORANGE, as a line comment
Scenario wording contradicts the test at docs/prs/2026-10-11-PR#88-codex-runner.md:108-119, severity unknown, counted as medium, hint, as a line comment
13 of 14 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 75193, calls 1, tokens in 72073 / out 13568 (reasoning included in out), duration 126.9 s, cost 0.0379 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11881, cost 0.0005 USD, finding judge `jev-1.13.0` calls 3, tokens in 5436, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 369, cost 0.0004 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 5120, cost 0.0071 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 37200, cost 0.0016 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.2 s, classifier 0.9 s, change_summary 31.5 s, doc_check 1.0 s, context 7.4 s, model_review 84.1 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `342e2248108cf9c99b0be49bffb0c61edb9a26e2` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:342e2248108cf9c99b0be49bffb0c61edb9a26e2 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,fa447656ff15a0765e6433e0752e6f39,acfe44aa855c3119b62a7c46f5418a42,e3bfb450fab604d690c77cd10d931b44,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,20887e9547a24897a4121521e049b072,b9c94dca42fbcf307ba0a4ecf63fbbeb,1f23a215ee5962d814b2b9f3cfba7b26,76a3fd6b6a10a177e4e973712e117067,9e93df245c716eda82b36ae73b956ce6,a38c07c53e226675b5d1ae0d4eb28c67,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,9ab015f9894956537a2a6036939aa887,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,2a99dc96027a4246d879d945b07c90bb,393c278aa56278e1cc97615e87089c82,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>342e224</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4193">the result for <code>98a07b9</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 2 finding(s) that Jev rates as probably real and severe: werkrevisor/codex.py:116-136, werkrevisor/codex.py:162-192
- **YELLOW** PR too large for an AI-only approval: 1007 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 given_when_then_misused (0.77 > yellow_above = 0.6)
- **YELLOW** model reports a security concern: Sensitive information exposure: `--sandbox read-only` is the only barrier between a prompt-injected Codex run and the network. The redactor only sanitises the response, so a successful injection can exfiltrate anything Codex reads (source, secrets, Gitea token leak via env) to an attacker host before any redaction happens. The auth_secrets filter also only catches strings of length 16 or more from…
- **hint** 16 changed file(s) that neither weaken the checks nor touch security 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** 14 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:108-119
- **hint** model recommends merge with caution
### Findings
1. **Short secrets bypass the redactor** at `werkrevisor/codex.py:116-136`, severity unknown, counted as medium, ORANGE, as a line comment
2. **Sandbox does not block the network** at `werkrevisor/codex.py:162-192`, severity unknown, counted as medium, ORANGE, as a line comment
3. **Scenario wording contradicts the test** at `docs/prs/2026-10-11-PR#88-codex-runner.md:108-119`, severity unknown, counted as medium, hint, as a line comment
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | given_when_then_misused | 0.77 | – | YELLOW |
13 of 14 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 75193, calls 1, tokens in 72073 / out 13568 (reasoning included in out), duration 126.9 s, cost 0.0379 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11881, cost 0.0005 USD, finding judge `jev-1.13.0` calls 3, tokens in 5436, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 369, cost 0.0004 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 5120, cost 0.0071 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 37200, cost 0.0016 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.2 s, classifier 0.9 s, change_summary 31.5 s, doc_check 1.0 s, context 7.4 s, model_review 84.1 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `342e2248108cf9c99b0be49bffb0c61edb9a26e2` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for 342e2248108cf9c99b0be49bffb0c61edb9a26e2.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `342e2248108cf9c99b0be49bffb0c61edb9a26e2`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:342e2248108cf9c99b0be49bffb0c61edb9a26e2 -->
Scenario wording contradicts the test, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.80, severity 1.6 of 3
Scenario#88.07 says: Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review / When werkrevisor reviews the same commit again / Then werkrevisor starts the automatic merge. But the verified test (test_a_codex_line_comment_holds_no_merge) starts with a writing-rule comment on a PR that is rated GREEN, replaces the body with the Codex marker, and asserts the merge is scheduled. The scenario describes "one unresolved comment of the Codex review", which is misleading: in the test the unresolved hint comes from a werkrevisor writing-rule comment that has been retrofitted with the Codex marker, not from a real Codex line comment. Either the scenario should be reworded to match the test (an open bot hint whose body carries the Codex marker), or the test should actually place a real Codex line comment into the worktree.
**Scenario wording contradicts the test**, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.80, severity 1.6 of 3
Scenario#88.07 says: Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review / When werkrevisor reviews the same commit again / Then werkrevisor starts the automatic merge. But the verified test (`test_a_codex_line_comment_holds_no_merge`) starts with a writing-rule comment on a PR that is rated GREEN, replaces the body with the Codex marker, and asserts the merge is scheduled. The scenario describes "one unresolved comment of the Codex review", which is misleading: in the test the unresolved hint comes from a werkrevisor writing-rule comment that has been retrofitted with the Codex marker, not from a real Codex line comment. Either the scenario should be reworded to match the test (an open bot hint whose body carries the Codex marker), or the test should actually place a real Codex line comment into the worktree.
Short secrets bypass the redactor, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.84, severity 3.0 of 3
auth_secrets collects only strings of length >= 16 from ~/.codex/auth.json. Anything shorter, e.g. an account_id or a future short-lived token, is added neither to the redact set nor to the unit test, so a prompt-injection that quotes such a value would leak it through the issue comment and the Codex line comments verbatim. The PR document claims "no token and no login reaches the PR"; the implementation only enforces that for long values. The threshold needs a justification (or a different approach), and the test test_the_login_values_are_secrets only covers strings of length 20 and 40, so it would not catch a regression that drops the threshold further.
**Short secrets bypass the redactor**, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.84, severity 3.0 of 3
`auth_secrets` collects only strings of length >= 16 from `~/.codex/auth.json`. Anything shorter, e.g. an `account_id` or a future short-lived token, is added neither to the redact set nor to the unit test, so a prompt-injection that quotes such a value would leak it through the issue comment and the Codex line comments verbatim. The PR document claims "no token and no login reaches the PR"; the implementation only enforces that for long values. The threshold needs a justification (or a different approach), and the test `test_the_login_values_are_secrets` only covers strings of length 20 and 40, so it would not catch a regression that drops the threshold further.
Fixed in 98a07b9: values of the login from 8 characters on are secrets now; the test covers a value of 10 characters, and it fails with the old limit of 16. Shorter values of auth.json are words like chatgpt; hiding them would garble the text.
Fixed in `98a07b9`: values of the login from 8 characters on are secrets now; the test covers a value of 10 characters, and it fails with the old limit of 16. Shorter values of `auth.json` are words like `chatgpt`; hiding them would garble the text.
Sandbox does not block the network, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.75, severity 3.0 of 3
codex exec ... --sandbox read-only in Codex CLI primarily restricts file writes, not network egress. The runner only sanitises the response of Codex with the Redactor, so a successful prompt injection in a PR description or repository can still make Codex send whatever it reads from the worktree (secrets, source, the Gitea token from any environment leak) to an attacker-controlled host before the response is ever returned. The README states "without network access to Gitea", which suggests this was intended to be off-limits. A deny-network option or an offline sandbox profile should be used for a review whose prompt comes from untrusted PR content.
**Sandbox does not block the network**, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.75, severity 3.0 of 3
`codex exec ... --sandbox read-only` in Codex CLI primarily restricts file writes, not network egress. The runner only sanitises the response of Codex with the Redactor, so a successful prompt injection in a PR description or repository can still make Codex send whatever it reads from the worktree (secrets, source, the Gitea token from any environment leak) to an attacker-controlled host before the response is ever returned. The README states "without network access to Gitea", which suggests this was intended to be off-limits. A deny-network option or an offline sandbox profile should be used for a review whose prompt comes from untrusted PR content.
Fixed in 98a07b9, with one correction: the sandbox of Codex already blocks the network of its commands; a probe inside the runner setup ended curl https://example.org with exit 6. The real gap was reading: read-only let Codex read every secret of the workstation. codex.run now starts Codex in bwrap with an empty home, except its login, the worktree and the programs; the same probe found no secrets.env any more. Codex gets no Gitea token in its environment, only HOME, PATH, LANG, TERM and CODEX_HOME.
Fixed in `98a07b9`, with one correction: the sandbox of Codex already blocks the network of its commands; a probe inside the runner setup ended `curl https://example.org` with exit 6. The real gap was reading: `read-only` let Codex read every secret of the workstation. `codex.run` now starts Codex in `bwrap` with an empty home, except its login, the worktree and the programs; the same probe found no `secrets.env` any more. Codex gets no Gitea token in its environment, only `HOME`, `PATH`, `LANG`, `TERM` and `CODEX_HOME`.
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ORANGE changes that weaken the checks according to Jev: tests/test_codex_eval.py (weakens checks 0.81)
ORANGE 1 finding(s) that Jev rates as probably real and severe: werkrevisor/codex.py:109-116
YELLOW tests lost or disabled: tests/test_codex_eval.py deleted
YELLOW PR too large for an AI-only approval: 1141 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 16 changed file(s) that neither weaken the checks nor touch security 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 15 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/gitea.py
hint files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:108-118
hint model recommends merge with caution
Findings
[medium] Incomplete answer validation at werkrevisor/codex.py:109-116, ORANGE, as a line comment
[low] Scenario Given/When/Then inconsistent with test at docs/prs/2026-10-11-PR#88-codex-runner.md:108-118, hint, as a line comment
14 of 15 units passed all questions (1 PR document(s)).
7 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 77053, calls 1, tokens in 73852 / out 51202 (reasoning included in out), duration 324.5 s, cost 0.0836 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12961, cost 0.0005 USD, finding judge `jev-1.13.0` calls 1, tokens in 1535, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 531, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 18615 / out 2814, cost 0.0089 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 33541, cost 0.0014 USD, build file judge `jev-1.13.0` calls 18, tokens in 24505, cost 0.0010 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 15.1 s, doc_check 0.9 s, context 8.0 s, model_review 297.6 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `98a07b945c3430456f872b75aa72e8852c4d80ca` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:98a07b945c3430456f872b75aa72e8852c4d80ca -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,c8133bfff53946c6965addbe8a5117a0,acfe44aa855c3119b62a7c46f5418a42,a25ae880d75e539255f40fbb2bd32d15,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,816547df70c632aa1dafb68659d356bd,254d0078e65b29fe92c69ad9cfe84f85,a38c07c53e226675b5d1ae0d4eb28c67,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,08128cf6a400763e9f5bf390ac8abd6c,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,d4be80dc977fa60a925a1b0058826abe,393c278aa56278e1cc97615e87089c82,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>98a07b9</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4200">the result for <code>45743f1</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** changes that weaken the checks according to Jev: tests/test_codex_eval.py (weakens checks 0.81)
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/codex.py:109-116
- **YELLOW** tests lost or disabled: tests/test_codex_eval.py deleted
- **YELLOW** PR too large for an AI-only approval: 1141 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 given_when_then_misused (0.78 > yellow_above = 0.6)
- **hint** 16 changed file(s) that neither weaken the checks nor touch security 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** 15 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/gitea.py
- **hint** files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:108-118
- **hint** model recommends merge with caution
### Findings
1. **[medium] Incomplete answer validation** at `werkrevisor/codex.py:109-116`, ORANGE, as a line comment
2. **[low] Scenario Given/When/Then inconsistent with test** at `docs/prs/2026-10-11-PR#88-codex-runner.md:108-118`, hint, as a line comment
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | given_when_then_misused | 0.78 | – | YELLOW |
14 of 15 units passed all questions (1 PR document(s)).
7 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 77053, calls 1, tokens in 73852 / out 51202 (reasoning included in out), duration 324.5 s, cost 0.0836 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12961, cost 0.0005 USD, finding judge `jev-1.13.0` calls 1, tokens in 1535, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 531, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 18615 / out 2814, cost 0.0089 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 33541, cost 0.0014 USD, build file judge `jev-1.13.0` calls 18, tokens in 24505, cost 0.0010 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 15.1 s, doc_check 0.9 s, context 8.0 s, model_review 297.6 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `98a07b945c3430456f872b75aa72e8852c4d80ca` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for 98a07b945c3430456f872b75aa72e8852c4d80ca.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `98a07b945c3430456f872b75aa72e8852c4d80ca`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:98a07b945c3430456f872b75aa72e8852c4d80ca -->
[low] Scenario Given/When/Then inconsistent with test (werkrevisor)
hint
Scenario#88.07 states: "Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review. When werkrevisor reviews the same commit again. Then werkrevisor starts the automatic merge." The Given describes a prior werkrevisor run (past tense "rated GREEN", "the same commit again") that the test test_a_codex_line_comment_holds_no_merge does not simulate — the test sets up a PR with one unresolved Codex line comment and runs werkrevisor once. The Given should describe the setup before the action (e.g. "a PR with one unresolved Codex line comment and no werkrevisor hints"), not the outcome.
**[low] Scenario Given/When/Then inconsistent with test** (werkrevisor)
hint
Scenario#88.07 states: "Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review. When werkrevisor reviews the same commit again. Then werkrevisor starts the automatic merge." The Given describes a prior werkrevisor run (past tense "rated GREEN", "the same commit again") that the test `test_a_codex_line_comment_holds_no_merge` does not simulate — the test sets up a PR with one unresolved Codex line comment and runs werkrevisor once. The Given should describe the setup before the action (e.g. "a PR with one unresolved Codex line comment and no werkrevisor hints"), not the outcome.
Fixed in 45743f1: the Given now names only the state before the run, a PR whose only unresolved line comment comes from Codex, as the test sets it up.
Fixed in `45743f1`: the Given now names only the state before the run, a PR whose only unresolved line comment comes from Codex, as the test sets it up.
valid_answer checks that each finding has severity, file, and line, but not title and explanation (both required by SCHEMA). If the Codex CLI silently does not enforce --output-schema, a finding with missing title or explanation would pass valid_answer but crash the runner in line_comment and result_comment when accessing finding['title'] or finding['explanation']. The crash is caught by the outer try/except in _review and treated as a failed run, so the impact is a degraded review (3 failed retries → error comment) instead of a posted comment with broken findings. Add isinstance(f.get("title"), str) and isinstance(f.get("explanation"), str) to the all(...) check, and (for completeness) verify answer.get("critical_reason") is a string.
**[medium] Incomplete answer validation** (werkrevisor)
ORANGE; Jev: real 0.73, severity 2.7 of 3
`valid_answer` checks that each finding has `severity`, `file`, and `line`, but not `title` and `explanation` (both required by `SCHEMA`). If the Codex CLI silently does not enforce `--output-schema`, a finding with missing `title` or `explanation` would pass `valid_answer` but crash the runner in `line_comment` and `result_comment` when accessing `finding['title']` or `finding['explanation']`. The crash is caught by the outer `try/except` in `_review` and treated as a failed run, so the impact is a degraded review (3 failed retries → error comment) instead of a posted comment with broken findings. Add `isinstance(f.get("title"), str)` and `isinstance(f.get("explanation"), str)` to the `all(...)` check, and (for completeness) verify `answer.get("critical_reason")` is a string.
Fixed in 45743f1: valid_answer also requires critical_reason, title and explanation as strings; the test covers a missing title and a missing explanation.
Fixed in `45743f1`: `valid_answer` also requires `critical_reason`, `title` and `explanation` as strings; the test covers a missing title and a missing explanation.
ai-review/assessment AI findings; a developer approval after checking them unlocks the merge; a human review request is pending; merge already scheduled
ORANGE 1 finding(s) that Jev rates as probably real and severe: werkrevisor/codexrunner.py:88-90
YELLOW tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
YELLOW PR too large for an AI-only approval: 1182 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 17 changed file(s) that neither weaken the checks nor touch security 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 15 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/config.py
hint files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
hint 1 finding(s) of low severity or rated minor by Jev: werkrevisor/codexrunner.py:276-283
hint model recommends merge with caution
Findings
Codex runner runs even when werkrevisor returns RED at werkrevisor/codexrunner.py:88-90, severity unknown, counted as medium, ORANGE, as a line comment
Status comparison uses untruncated description at werkrevisor/codexrunner.py:276-283, severity unknown, counted as medium, hint, as a line comment
14 of 15 units passed all questions (1 PR document(s)).
4 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 68746, calls 1, tokens in 65892 / out 45314 (reasoning included in out), duration 300.3 s, cost 0.0741 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12967, cost 0.0005 USD, finding judge `jev-1.13.0` calls 2, tokens in 2995, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 577, cost 0.0025 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19441 / out 2705, cost 0.0090 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 40357, cost 0.0017 USD, build file judge `jev-1.13.0` calls 18, tokens in 25373, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 19.9 s, doc_check 1.0 s, context 9.2 s, model_review 267.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `45743f10d24a1d546234c2ddca9cb9ce1b189b09` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:45743f10d24a1d546234c2ddca9cb9ce1b189b09 -->
<!-- werkrevisor-verdict:ORANGE -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,c8133bfff53946c6965addbe8a5117a0,acfe44aa855c3119b62a7c46f5418a42,b1bab88859cd864fc5076d5b2aba5ecd,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,9807a23833e7539dbafb504b6e0c40a2,e0811364b4ca72a02890189be5dd3d3a,5b14cb314cd73cbbae4e7d1ea64fc76e,db72e5b8fb90ea8882e34b907b3c5b61,3df42bd508350a2f5bd6d2992759f6ab,98ba1c5b959a403816e09c50446b68f2,ff414472b984dcfac08d50169f9a3bb5,404e2e4c38d3eb5cce87f16d4f5aa6ad,2921157973324a0b0170222e7b869979,328b7d73a7c39eb9f8282cc45e12c010,a38c07c53e226675b5d1ae0d4eb28c67,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,08128cf6a400763e9f5bf390ac8abd6c,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,4e44805076885b16d8331a2c83474dc5,393c278aa56278e1cc97615e87089c82,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟠 werkrevisor ORANGE for <code>45743f1</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4207">the result for <code>16af857</code></a></summary>
## 🟠 werkrevisor: ORANGE / FINDINGS
Change kind: `mixed`.
### Reasons
- **ORANGE** 1 finding(s) that Jev rates as probably real and severe: werkrevisor/codexrunner.py:88-90
- **YELLOW** tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
- **YELLOW** PR too large for an AI-only approval: 1182 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 given_when_then_misused (0.74 > yellow_above = 0.6)
- **hint** 17 changed file(s) that neither weaken the checks nor touch security 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** 15 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/config.py
- **hint** files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
- **hint** 1 finding(s) of low severity or rated minor by Jev: werkrevisor/codexrunner.py:276-283
- **hint** model recommends merge with caution
### Findings
1. **Codex runner runs even when werkrevisor returns RED** at `werkrevisor/codexrunner.py:88-90`, severity unknown, counted as medium, ORANGE, as a line comment
2. **Status comparison uses untruncated description** at `werkrevisor/codexrunner.py:276-283`, severity unknown, counted as medium, hint, as a line comment
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | given_when_then_misused | 0.74 | – | YELLOW |
14 of 15 units passed all questions (1 PR document(s)).
4 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 68746, calls 1, tokens in 65892 / out 45314 (reasoning included in out), duration 300.3 s, cost 0.0741 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12967, cost 0.0005 USD, finding judge `jev-1.13.0` calls 2, tokens in 2995, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 577, cost 0.0025 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19441 / out 2705, cost 0.0090 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 40357, cost 0.0017 USD, build file judge `jev-1.13.0` calls 18, tokens in 25373, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 19.9 s, doc_check 1.0 s, context 9.2 s, model_review 267.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `45743f10d24a1d546234c2ddca9cb9ce1b189b09` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
</details>
werkrevisor: ORANGE / FINDINGS for 45743f10d24a1d546234c2ddca9cb9ce1b189b09.
The result comment of werkrevisor holds the details.
werkrevisor: ORANGE / FINDINGS for `45743f10d24a1d546234c2ddca9cb9ce1b189b09`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:45743f10d24a1d546234c2ddca9cb9ce1b189b09 -->
Codex runner runs even when werkrevisor returns RED, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.71, severity 3.0 of 3
The function has_werkrevisor_result returns True for any non-None verdict (GREEN, YELLOW, or RED), so the runner proceeds to invoke the Codex CLI for PRs that werkrevisor has already blocked. This wastes the subscription quota and posts review results on PRs that cannot merge. The PR document's Scenario#88.02 is titled "a PR waits for the result of werkrevisor", implying a wait for a passing result, but the implementation only waits for the presence of any result comment. The check should verify the verdict value (e.g., GREEN or YELLOW with approval) before consuming quota.
**Codex runner runs even when werkrevisor returns RED**, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.71, severity 3.0 of 3
The function `has_werkrevisor_result` returns True for any non-None verdict (GREEN, YELLOW, or RED), so the runner proceeds to invoke the Codex CLI for PRs that werkrevisor has already blocked. This wastes the subscription quota and posts review results on PRs that cannot merge. The PR document's Scenario#88.02 is titled "a PR waits for the result of werkrevisor", implying a wait for a passing result, but the implementation only waits for the presence of any result comment. The check should verify the verdict value (e.g., GREEN or YELLOW with approval) before consuming quota.
Status comparison uses untruncated description, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.74, severity 2.2 of 3
Runner.set_status compares the full description to the description stored from the previous call, but GiteaClient.set_status truncates descriptions to 250 characters before sending. When a description exceeds 250 characters, the comparison always fails and the status is rewritten every run, wasting API calls and cluttering the status history. All current descriptions are short, so this latent bug does not manifest today.
**Status comparison uses untruncated description**, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.74, severity 2.2 of 3
`Runner.set_status` compares the full description to the description stored from the previous call, but `GiteaClient.set_status` truncates descriptions to 250 characters before sending. When a description exceeds 250 characters, the comparison always fails and the status is rewritten every run, wasting API calls and cluttering the status history. All current descriptions are short, so this latent bug does not manifest today.
YELLOW tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
YELLOW PR too large for an AI-only approval: 1190 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 17 changed file(s) that neither weaken the checks nor touch security 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 PR document not compared with a change summary: the summary by openrouter/minimax/minimax-m3 failed: the answer holds no list of changes
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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/config.py
hint files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
hint 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:142-152
Findings
Doc inconsistency in summary at docs/prs/2026-10-11-PR#88-codex-runner.md:142-152, severity unknown, counted as medium, hint, as a line comment
14 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 70422, calls 1, tokens in 67497 / out 34054 (reasoning included in out), duration 296.3 s, cost 0.0611 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13662, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1935, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 799, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19626 / out 16000, cost 0.0251 USD (reported), build file judge `jev-1.13.0` calls 18, tokens in 25572, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 77.7 s, context 10.8 s, model_review 205.1 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `16af857e267dac517fd222b68a3ce517a8ddfd3c` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:16af857e267dac517fd222b68a3ce517a8ddfd3c -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,c8133bfff53946c6965addbe8a5117a0,acfe44aa855c3119b62a7c46f5418a42,3be3c95ca80c029b7c0dce070bad66ab,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,9807a23833e7539dbafb504b6e0c40a2,e0811364b4ca72a02890189be5dd3d3a,5b14cb314cd73cbbae4e7d1ea64fc76e,db72e5b8fb90ea8882e34b907b3c5b61,3df42bd508350a2f5bd6d2992759f6ab,98ba1c5b959a403816e09c50446b68f2,ff414472b984dcfac08d50169f9a3bb5,404e2e4c38d3eb5cce87f16d4f5aa6ad,2921157973324a0b0170222e7b869979,328b7d73a7c39eb9f8282cc45e12c010,93040e78cff19c88b942130f3bbab33f,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,08128cf6a400763e9f5bf390ac8abd6c,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,4e44805076885b16d8331a2c83474dc5,57b8472efc4633f113cafaf89976a002,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
<!-- werkrevisor-folded -->
<details><summary>🟡 werkrevisor YELLOW for <code>16af857</code>, superseded by <a href="http://git.javagil.de/mi/werkrevisor/pulls/88#issuecomment-4212">the result for <code>8e89649</code></a></summary>
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
- **YELLOW** PR too large for an AI-only approval: 1190 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.02 more_than_one_aspect (0.66 > yellow_above = 0.6)
- **YELLOW** spec: docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 given_when_then_misused (0.70 > yellow_above = 0.6)
- **hint** 17 changed file(s) that neither weaken the checks nor touch security 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** PR document not compared with a change summary: the summary by openrouter/minimax/minimax-m3 failed: the answer holds no list of changes
- **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 as excerpt of the selected lines and 5 lines around each changed line, not in full (all full files together would exceed [review] max_full_files_chars = 160000): werkrevisor/config.py
- **hint** files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
- **hint** 1 finding(s) of low severity or rated minor by Jev: docs/prs/2026-10-11-PR#88-codex-runner.md:142-152
### Findings
1. **Doc inconsistency in summary** at `docs/prs/2026-10-11-PR#88-codex-runner.md:142-152`, severity unknown, counted as medium, hint, as a line comment
### Classifier
| Unit | Question | Problem | Confidence | Verdict |
|---|---|---|---|---|
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.02 | more_than_one_aspect | 0.66 | – | YELLOW |
| docs/prs/2026-10-11-PR#88-codex-runner.md Scenario#88.07 | given_when_then_misused | 0.70 | – | YELLOW |
14 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 70422, calls 1, tokens in 67497 / out 34054 (reasoning included in out), duration 296.3 s, cost 0.0611 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13662, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1935, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 799, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19626 / out 16000, cost 0.0251 USD (reported), build file judge `jev-1.13.0` calls 18, tokens in 25572, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 77.7 s, context 10.8 s, model_review 205.1 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `16af857e267dac517fd222b68a3ce517a8ddfd3c` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
</details>
werkrevisor: YELLOW / HUMAN_REVIEW for 16af857e267dac517fd222b68a3ce517a8ddfd3c.
The result comment of werkrevisor holds the details.
werkrevisor: YELLOW / HUMAN_REVIEW for `16af857e267dac517fd222b68a3ce517a8ddfd3c`.
The result comment of werkrevisor holds the details.
<!-- werkrevisor-review:16af857e267dac517fd222b68a3ce517a8ddfd3c -->
Doc inconsistency in summary, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.83, severity 1.9 of 3
The "Decisions" and "Implementation" bullets say human approval is required "when Codex rates the PR as critical", but the gate logic in werkrevisor/codexrunner.py also requires human approval when there is any unattached finding (a finding outside the diff). Scenario#88.04 in the same document already states the full rule ("critical PR or a finding outside the diff"), so a reader relying only on the summary bullet would miss the unattached-finding case. Tighten the summary so it matches the scenarios and the gate_state logic.
**Doc inconsistency in summary**, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.83, severity 1.9 of 3
The "Decisions" and "Implementation" bullets say human approval is required "when Codex rates the PR as critical", but the gate logic in werkrevisor/codexrunner.py also requires human approval when there is any unattached finding (a finding outside the diff). Scenario#88.04 in the same document already states the full rule ("critical PR or a finding outside the diff"), so a reader relying only on the summary bullet would miss the unattached-finding case. Tighten the summary so it matches the scenarios and the gate_state logic.
YELLOW tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
YELLOW PR too large for an AI-only approval: 1194 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
hint 17 changed file(s) that neither weaken the checks nor touch security 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 17 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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/gitea.py (advisory: Jev judged every changed file)
hint files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
Classifier
17 of 17 units passed all questions (1 PR document(s)).
6 answers ignored because of a confidence below [classifier] min_confidence.
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 79128, calls 1, tokens in 75870 / out 36670 (reasoning included in out), duration 200.1 s, cost 0.0667 USD (reported), classifier `jev-1.13.0` calls 17, tokens in 14556, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 603, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19678 / out 2034, cost 0.0083 USD (reported), PR document check `jev-1.13.0` calls 17, tokens in 35067, cost 0.0015 USD, build file judge `jev-1.13.0` calls 18, tokens in 25626, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 1.1 s, change_summary 9.4 s, doc_check 1.1 s, context 7.8 s, model_review 179.1 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).
Reviewed head `8e896495155bbed4e380ba60c0ac45e7d6e39b93` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
<!-- werkrevisor:8e896495155bbed4e380ba60c0ac45e7d6e39b93 -->
<!-- werkrevisor-verdict:YELLOW -->
<!-- werkrevisor-blocks:17796c5b7b2213c97e392f7f56e1f3d3,c8133bfff53946c6965addbe8a5117a0,acfe44aa855c3119b62a7c46f5418a42,32c52fee50cb04583ec1799c38d527f3,3f74628b8e024196d512247a40a7dc95,72cccdce41f821d1f05cecda02e0c66d,ab7e8b0a5e350d900e914952af03f799,0173d2123b583e9b0ba3f46f5a6b7829,9807a23833e7539dbafb504b6e0c40a2,e0811364b4ca72a02890189be5dd3d3a,5b14cb314cd73cbbae4e7d1ea64fc76e,db72e5b8fb90ea8882e34b907b3c5b61,3df42bd508350a2f5bd6d2992759f6ab,98ba1c5b959a403816e09c50446b68f2,ff414472b984dcfac08d50169f9a3bb5,404e2e4c38d3eb5cce87f16d4f5aa6ad,2921157973324a0b0170222e7b869979,328b7d73a7c39eb9f8282cc45e12c010,f455cd36a6fa9042e1cee371f76851cf,bc3ed529562f61f1b76bd6fcbf5e1765,8215ebc94282b538829d1e1602ea1f97,1cbc582dd41ef5389cace65a2978347a,08128cf6a400763e9f5bf390ac8abd6c,49d1cee554e4911bfb4da800ad318161,32a104a8be61a64097bce0a8af20afe7,f7f6026b6c8e24bacef5ec45853eb4f3,3ab9f8fbd7a17edd2d6d9c8dcc348d30,f1cf2622a07a72ac0740bef86a8c4986,be89d1ce268cf6887dfeed05b332e757,57c3ee2defa26a9401cb3a98d0af7694,f22061e23019b42a8baadc22bc3fbf6f,835b38d98e7db5d8006aa7fec6df3e91,0d38c6690943bbfeee7eb247100673e4,15c1cab920cc9768dbeba28a8f80d8e5,2d8c8e3873c4cc965aee70e15396361b,ac7b8351013d994ae56850bb00197bb1,4399afbb02ca51956e02685139c0ee00,b6572390b4bce4279c37367a59c4700c,7fc0579e99be393eb431bfbbfc438206,b6c84e7f7f86f404840bcd6b5bd943e4,a4351127c9a41290c8488f5abcc9ced2,8c48cfc809fd19d7bb2f00c2f9d41033,4e44805076885b16d8331a2c83474dc5,57b8472efc4633f113cafaf89976a002,25205649c12c1ba0d79b5dfb1db39e4d,fa45b06eb636ebf14924379d97b24c26,0b66155daabf87ab96a8202b91a33f72,49af1d195fd6d4dac60da0ca3fc7ae98,c26522e195feb16ee98ab099d84a693e,21640d24cebdcfefa6050fcd1c332fb2,102d73d44c732282de66cc911a491edb,caf03fab9d2ce34eaddf61eac25d8f5a,0cfa30bfb748adcd46f27ee7bbcd3c12,2b5cbec1544f53c14f1820e2d973e00b,97c8c73703b840d14365bdea5ad17e77 -->
## 🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind: `mixed`.
### Reasons
- **YELLOW** tests lost or disabled: tests/test_codex_eval.py:17 removes 5 test(s) or assertion(s) without a replacement
- **YELLOW** PR too large for an AI-only approval: 1194 changed lines (docs and mechanical files not counted) exceed [size] max_changed_lines = 800; please review it yourself
- **hint** 17 changed file(s) that neither weaken the checks nor touch security 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** 17 section(s) of the PR document agree with the change summary of openrouter/minimax/minimax-m3 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/gitea.py (advisory: Jev judged every changed file)
- **hint** files the model cannot review: docs/werkrevisor-pr-workflow-dark.svg, docs/werkrevisor-pr-workflow.svg (advisory: Jev judged every changed file)
### Classifier
17 of 17 units passed all questions (1 PR document(s)).
6 answers ignored because of a confidence below [classifier] min_confidence.
<sub>
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 79128, calls 1, tokens in 75870 / out 36670 (reasoning included in out), duration 200.1 s, cost 0.0667 USD (reported), classifier `jev-1.13.0` calls 17, tokens in 14556, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 603, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19678 / out 2034, cost 0.0083 USD (reported), PR document check `jev-1.13.0` calls 17, tokens in 35067, cost 0.0015 USD, build file judge `jev-1.13.0` calls 18, tokens in 25626, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 1.1 s, change_summary 9.4 s, doc_check 1.1 s, context 7.8 s, model_review 179.1 s, config: defaults + host + repository (.werkrevisor.toml at main 08b725e).<br>
Reviewed head `8e896495155bbed4e380ba60c0ac45e7d6e39b93` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
</sub>
tests lost or disabled in tests/test_codex_eval.py: no test is lost.
The four tests of PR#87 moved with their code to tests/test_codex.py (werkrevisor/codex.py); tests/test_codex_eval.py now tests tools/codex-eval itself. See "Additional Changes" in the PR document.
PR too large for an AI-only approval (1194 lines): structural; the runner, its tests and the jail belong together.
The approval is up to the human.
All line comments of the earlier rounds are fixed and resolved; 679 tests pass.
Answer to the review of `8e89649`:
- **tests lost or disabled** in `tests/test_codex_eval.py`: no test is lost.
The four tests of PR#87 moved with their code to `tests/test_codex.py` (`werkrevisor/codex.py`);
`tests/test_codex_eval.py` now tests `tools/codex-eval` itself. See "Additional Changes" in the PR document.
- **PR too large for an AI-only approval** (1194 lines): structural; the runner, its tests and the jail belong together.
The approval is up to the human.
All line comments of the earlier rounds are fixed and resolved; 679 tests pass.
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.
Design and implementation of #model.codex.gate: a runner on the workstation reviews PRs with the Codex CLI after werkrevisor.
🤖 Generated with Claude Code
🟡 werkrevisor YELLOW for
659d873, superseded by the result foraf6613e🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Findings
docs/prs/2026-10-11-PR#88-codex-runner.md:39-45, hint, as a line commentClassifier
12 of 14 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 75163, calls 1, tokens in 72046 / out 29516 (reasoning included in out), duration 323.5 s, cost 0.0570 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11841, cost 0.0005 USD, finding judge `none` calls 0, tokens in 0, cost 0.0000 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 282, cost 0.0028 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 6478, cost 0.0127 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 43586, cost 0.0018 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 39.1 s, doc_check 0.9 s, context 4.1 s, model_review 276.9 s, finding_judge 0.0 s, config: defaults + host + repository (.werkrevisor.toml at main4 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `659d8736955db01cd56bb146ee256e02ec8260db` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
werkrevisor: YELLOW / HUMAN_REVIEW for
659d8736955db01cd56bb146ee256e02ec8260db.The result comment of werkrevisor holds the details.
@@ -0,0 +36,4 @@- [test_codexrunner.CodexRunnerTest.test_a_repository_without_a_codex_mode_gets_no_review](../../tests/test_codexrunner.py)- [test_config_layers.LayeringTest.test_the_repository_chooses_the_codex_mode](../../tests/test_config_layers.py)#### Scenario#88.02: a PR waits for the result of werkrevisor[low] Doc-code mismatch on WIP pending status (werkrevisor)
hint
Scenario#88.02 states that in
gatemode the statusai-review/codexbecomes "pending" both for a WIP PR and for a PR without a werkrevisor result. In the implementation,run_repositoryskips WIP PRs withcontinueand sets no status at all; the "waiting for the Codex review" pending status is only emitted fromrun_prfor non-WIP PRs that have no werkrevisor result. The testtest_a_pr_waits_for_werkrevisor_and_its_wip_endonly assertsruns == 0for the WIP sub-case, never the status, so the contradiction is uncovered.Fixed in
af6613e: a WIP PR gets no status at all; only a PR without "WIP: " and without a result of werkrevisor getspendingingatemode, asrun_prdoes.🟡 werkrevisor YELLOW for
af6613e, superseded by the result fora42e5a0🟡 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 74590, calls 1, tokens in 71502 / out 38227 (reasoning included in out), duration 396.5 s, cost 0.0673 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11874, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 527, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 3064, cost 0.0047 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 42023, cost 0.0018 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 18.3 s, doc_check 0.9 s, context 8.0 s, model_review 366.8 s, config: defaults + host + repository (.werkrevisor.toml at main3 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `af6613e2cfff7e9010197426c4ca28d133389dd9` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
🟡 werkrevisor YELLOW for
a42e5a0, superseded by the result for342e224🟡 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 74899, calls 1, tokens in 71801 / out 33130 (reasoning included in out), duration 227.9 s, cost 0.0613 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11886, cost 0.0005 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 267, cost 0.0003 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 2446, cost 0.0039 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 34419, cost 0.0014 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 16.1 s, doc_check 0.9 s, context 4.4 s, model_review 204.0 s, config: defaults + host + repository (.werkrevisor.toml at main4 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `a42e5a0c478d79a993d2aad6034d32db62d7e055` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
🟠 werkrevisor ORANGE for
342e224, superseded by the result for98a07b9🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
--sandbox read-onlyis the only barrier between a prompt-injected Codex run and the network. The redactor only sanitises the response, so a successful injection can exfiltrate anything Codex reads (source, secrets, Gitea token leak via env) to an attacker host before any redaction happens. The auth_secrets filter also only catches strings of length 16 or more from…Findings
Short secrets bypass the redactor at
werkrevisor/codex.py:116-136, severity unknown, counted as medium, ORANGE, as a line commentSandbox does not block the network at
werkrevisor/codex.py:162-192, severity unknown, counted as medium, ORANGE, as a line commentScenario wording contradicts the test at
docs/prs/2026-10-11-PR#88-codex-runner.md:108-119, severity unknown, counted as medium, hint, as a line commentClassifier
13 of 14 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 75193, calls 1, tokens in 72073 / out 13568 (reasoning included in out), duration 126.9 s, cost 0.0379 USD (reported), classifier `jev-1.13.0` calls 14, tokens in 11881, cost 0.0005 USD, finding judge `jev-1.13.0` calls 3, tokens in 5436, cost 0.0002 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 1, tokens in 21529 / out 369, cost 0.0004 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 16512 / out 5120, cost 0.0071 USD (reported), PR document check `jev-1.13.0` calls 14, tokens in 37200, cost 0.0016 USD, build file judge `jev-1.13.0` calls 17, tokens in 22051, cost 0.0009 USD, phases: path_judge 1.2 s, classifier 0.9 s, change_summary 31.5 s, doc_check 1.0 s, context 7.4 s, model_review 84.1 s, finding_judge 0.3 s, config: defaults + host + repository (.werkrevisor.toml at main5 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `342e2248108cf9c99b0be49bffb0c61edb9a26e2` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
werkrevisor: ORANGE / FINDINGS for
342e2248108cf9c99b0be49bffb0c61edb9a26e2.The result comment of werkrevisor holds the details.
@@ -0,0 +105,4 @@- [test_codexrunner.CodexRunnerTest.test_no_token_or_login_reaches_the_pr](../../tests/test_codexrunner.py)- [test_codex.CodexTest.test_the_login_values_are_secrets](../../tests/test_codex.py)#### Scenario#88.07: werkrevisor does not wait for Codex commentsScenario wording contradicts the test, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.80, severity 1.6 of 3
Scenario#88.07 says: Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review / When werkrevisor reviews the same commit again / Then werkrevisor starts the automatic merge. But the verified test (
test_a_codex_line_comment_holds_no_merge) starts with a writing-rule comment on a PR that is rated GREEN, replaces the body with the Codex marker, and asserts the merge is scheduled. The scenario describes "one unresolved comment of the Codex review", which is misleading: in the test the unresolved hint comes from a werkrevisor writing-rule comment that has been retrofitted with the Codex marker, not from a real Codex line comment. Either the scenario should be reworded to match the test (an open bot hint whose body carries the Codex marker), or the test should actually place a real Codex line comment into the worktree.Fixed in
98a07b9: the test now adds a real Codex review with a line comment before werkrevisor runs, instead of rewriting a writing-rule comment.@@ -0,0 +113,4 @@and isinstance(f.get("line"), int) and not isinstance(f.get("line"), bool) for f in findings)def auth_secrets(codex_home=None):Short secrets bypass the redactor, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.84, severity 3.0 of 3
auth_secretscollects only strings of length >= 16 from~/.codex/auth.json. Anything shorter, e.g. anaccount_idor a future short-lived token, is added neither to the redact set nor to the unit test, so a prompt-injection that quotes such a value would leak it through the issue comment and the Codex line comments verbatim. The PR document claims "no token and no login reaches the PR"; the implementation only enforces that for long values. The threshold needs a justification (or a different approach), and the testtest_the_login_values_are_secretsonly covers strings of length 20 and 40, so it would not catch a regression that drops the threshold further.Fixed in
98a07b9: values of the login from 8 characters on are secrets now; the test covers a value of 10 characters, and it fails with the old limit of 16. Shorter values ofauth.jsonare words likechatgpt; hiding them would garble the text.@@ -0,0 +159,4 @@return workdef run(work, prompt, model, effort, timeout_seconds=1800):Sandbox does not block the network, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.75, severity 3.0 of 3
codex exec ... --sandbox read-onlyin Codex CLI primarily restricts file writes, not network egress. The runner only sanitises the response of Codex with the Redactor, so a successful prompt injection in a PR description or repository can still make Codex send whatever it reads from the worktree (secrets, source, the Gitea token from any environment leak) to an attacker-controlled host before the response is ever returned. The README states "without network access to Gitea", which suggests this was intended to be off-limits. A deny-network option or an offline sandbox profile should be used for a review whose prompt comes from untrusted PR content.Fixed in
98a07b9, with one correction: the sandbox of Codex already blocks the network of its commands; a probe inside the runner setup endedcurl https://example.orgwith exit 6. The real gap was reading:read-onlylet Codex read every secret of the workstation.codex.runnow starts Codex inbwrapwith an empty home, except its login, the worktree and the programs; the same probe found nosecrets.envany more. Codex gets no Gitea token in its environment, onlyHOME,PATH,LANG,TERMandCODEX_HOME.🟠 werkrevisor ORANGE for
98a07b9, superseded by the result for45743f1🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
[medium] Incomplete answer validation at
werkrevisor/codex.py:109-116, ORANGE, as a line comment[low] Scenario Given/When/Then inconsistent with test at
docs/prs/2026-10-11-PR#88-codex-runner.md:108-118, hint, as a line commentClassifier
14 of 15 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 77053, calls 1, tokens in 73852 / out 51202 (reasoning included in out), duration 324.5 s, cost 0.0836 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12961, cost 0.0005 USD, finding judge `jev-1.13.0` calls 1, tokens in 1535, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 531, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 18615 / out 2814, cost 0.0089 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 33541, cost 0.0014 USD, build file judge `jev-1.13.0` calls 18, tokens in 24505, cost 0.0010 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 15.1 s, doc_check 0.9 s, context 8.0 s, model_review 297.6 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main7 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `98a07b945c3430456f872b75aa72e8852c4d80ca` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
werkrevisor: ORANGE / FINDINGS for
98a07b945c3430456f872b75aa72e8852c4d80ca.The result comment of werkrevisor holds the details.
@@ -0,0 +105,4 @@- [test_codexrunner.CodexRunnerTest.test_no_token_or_login_reaches_the_pr](../../tests/test_codexrunner.py)- [test_codex.CodexTest.test_the_login_values_are_secrets](../../tests/test_codex.py)#### Scenario#88.07: werkrevisor does not wait for Codex comments[low] Scenario Given/When/Then inconsistent with test (werkrevisor)
hint
Scenario#88.07 states: "Given a PR that werkrevisor rated GREEN, with one unresolved comment of the Codex review. When werkrevisor reviews the same commit again. Then werkrevisor starts the automatic merge." The Given describes a prior werkrevisor run (past tense "rated GREEN", "the same commit again") that the test
test_a_codex_line_comment_holds_no_mergedoes not simulate — the test sets up a PR with one unresolved Codex line comment and runs werkrevisor once. The Given should describe the setup before the action (e.g. "a PR with one unresolved Codex line comment and no werkrevisor hints"), not the outcome.Fixed in
45743f1: the Given now names only the state before the run, a PR whose only unresolved line comment comes from Codex, as the test sets it up.@@ -0,0 +106,4 @@return usage, commands, errorsdef valid_answer(answer):[medium] Incomplete answer validation (werkrevisor)
ORANGE; Jev: real 0.73, severity 2.7 of 3
valid_answerchecks that each finding hasseverity,file, andline, but nottitleandexplanation(both required bySCHEMA). If the Codex CLI silently does not enforce--output-schema, a finding with missingtitleorexplanationwould passvalid_answerbut crash the runner inline_commentandresult_commentwhen accessingfinding['title']orfinding['explanation']. The crash is caught by the outertry/exceptin_reviewand treated as a failed run, so the impact is a degraded review (3 failed retries → error comment) instead of a posted comment with broken findings. Addisinstance(f.get("title"), str)andisinstance(f.get("explanation"), str)to theall(...)check, and (for completeness) verifyanswer.get("critical_reason")is a string.Fixed in
45743f1:valid_answeralso requirescritical_reason,titleandexplanationas strings; the test covers a missing title and a missing explanation.🟠 werkrevisor ORANGE for
45743f1, superseded by the result for16af857🟠 werkrevisor: ORANGE / FINDINGS
Change kind:
mixed.Reasons
Findings
Codex runner runs even when werkrevisor returns RED at
werkrevisor/codexrunner.py:88-90, severity unknown, counted as medium, ORANGE, as a line commentStatus comparison uses untruncated description at
werkrevisor/codexrunner.py:276-283, severity unknown, counted as medium, hint, as a line commentClassifier
14 of 15 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 68746, calls 1, tokens in 65892 / out 45314 (reasoning included in out), duration 300.3 s, cost 0.0741 USD (reported), classifier `jev-1.13.0` calls 15, tokens in 12967, cost 0.0005 USD, finding judge `jev-1.13.0` calls 2, tokens in 2995, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 577, cost 0.0025 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19441 / out 2705, cost 0.0090 USD (reported), PR document check `jev-1.13.0` calls 15, tokens in 40357, cost 0.0017 USD, build file judge `jev-1.13.0` calls 18, tokens in 25373, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 19.9 s, doc_check 1.0 s, context 9.2 s, model_review 267.4 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main4 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `45743f10d24a1d546234c2ddca9cb9ce1b189b09` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
werkrevisor: ORANGE / FINDINGS for
45743f10d24a1d546234c2ddca9cb9ce1b189b09.The result comment of werkrevisor holds the details.
@@ -0,0 +85,4 @@return None, Falsedef has_werkrevisor_result(comments, head, login):Codex runner runs even when werkrevisor returns RED, severity unknown, counted as medium (werkrevisor)
ORANGE; Jev: real 0.71, severity 3.0 of 3
The function
has_werkrevisor_resultreturns True for any non-None verdict (GREEN, YELLOW, or RED), so the runner proceeds to invoke the Codex CLI for PRs that werkrevisor has already blocked. This wastes the subscription quota and posts review results on PRs that cannot merge. The PR document's Scenario#88.02 is titled "a PR waits for the result of werkrevisor", implying a wait for a passing result, but the implementation only waits for the presence of any result comment. The check should verify the verdict value (e.g., GREEN or YELLOW with approval) before consuming quota.Fixed in
16af857: the runner reviews only a head that werkrevisor rated GREEN, YELLOW or ORANGE; the test covers a RED head.@@ -0,0 +273,4 @@f"{len(findings)} finding(s), {record['seconds']} s")return comment, Falsedef set_status(self, gitea, head, state, description):Status comparison uses untruncated description, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.74, severity 2.2 of 3
Runner.set_statuscompares the full description to the description stored from the previous call, butGiteaClient.set_statustruncates descriptions to 250 characters before sending. When a description exceeds 250 characters, the comparison always fails and the status is rewritten every run, wasting API calls and cluttering the status history. All current descriptions are short, so this latent bug does not manifest today.Fixed in
16af857: the comparison uses the first 250 characters, as Gitea keeps them; the test covers a description of 300 characters.🟡 werkrevisor YELLOW for
16af857, superseded by the result for8e89649🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Findings
docs/prs/2026-10-11-PR#88-codex-runner.md:142-152, severity unknown, counted as medium, hint, as a line commentClassifier
14 of 16 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 70422, calls 1, tokens in 67497 / out 34054 (reasoning included in out), duration 296.3 s, cost 0.0611 USD (reported), classifier `jev-1.13.0` calls 16, tokens in 13662, cost 0.0006 USD, finding judge `jev-1.13.0` calls 1, tokens in 1935, cost 0.0001 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 37773 / out 799, cost 0.0008 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19626 / out 16000, cost 0.0251 USD (reported), build file judge `jev-1.13.0` calls 18, tokens in 25572, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 0.9 s, change_summary 77.7 s, context 10.8 s, model_review 205.1 s, finding_judge 0.2 s, config: defaults + host + repository (.werkrevisor.toml at main5 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `16af857e267dac517fd222b68a3ce517a8ddfd3c` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
werkrevisor: YELLOW / HUMAN_REVIEW for
16af857e267dac517fd222b68a3ce517a8ddfd3c.The result comment of werkrevisor holds the details.
@@ -0,0 +139,4 @@Reason: the login of the subscription must not reach a shared server or a build container;a Codex review exists only while the workstation runs.- `.werkrevisor.toml` chooses per repository whether and how the Codex review acts, with `[codex] mode`:`off`, the default, means no Codex review;Doc inconsistency in summary, severity unknown, counted as medium (werkrevisor)
hint; Jev: real 0.83, severity 1.9 of 3
The "Decisions" and "Implementation" bullets say human approval is required "when Codex rates the PR as critical", but the gate logic in werkrevisor/codexrunner.py also requires human approval when there is any unattached finding (a finding outside the diff). Scenario#88.04 in the same document already states the full rule ("critical PR or a finding outside the diff"), so a reader relying only on the summary bullet would miss the unattached-finding case. Tighten the summary so it matches the scenarios and the gate_state logic.
Fixed in
8e89649: both bullets now name the critical PR and the finding outside the diff, asgate_statedoes.🟡 werkrevisor: YELLOW / HUMAN_REVIEW
Change kind:
mixed.Reasons
Classifier
17 of 17 units passed all questions (1 PR document(s)).
Usage: model `openrouter/minimax/minimax-m3`, LLM done, tokens counted before the call 79128, calls 1, tokens in 75870 / out 36670 (reasoning included in out), duration 200.1 s, cost 0.0667 USD (reported), classifier `jev-1.13.0` calls 17, tokens in 14556, cost 0.0006 USD, excerpt selection `openrouter/openai/gpt-6-luna` calls 2, tokens in 24026 / out 603, cost 0.0005 USD (reported), change summary `openrouter/minimax/minimax-m3` via Minimax calls 1, tokens in 19678 / out 2034, cost 0.0083 USD (reported), PR document check `jev-1.13.0` calls 17, tokens in 35067, cost 0.0015 USD, build file judge `jev-1.13.0` calls 18, tokens in 25626, cost 0.0011 USD, phases: path_judge 1.1 s, classifier 1.1 s, change_summary 9.4 s, doc_check 1.1 s, context 7.8 s, model_review 179.1 s, config: defaults + host + repository (.werkrevisor.toml at main6 answers ignored because of a confidence below [classifier] min_confidence.
08b725e).Reviewed head `8e896495155bbed4e380ba60c0ac45e7d6e39b93` against base `08b725e23a224e9f818ec693b644dfaa12a54baa`, werkrevisor 0.33.0.
Answer to the review of
8e89649:tests/test_codex_eval.py: no test is lost.The four tests of PR#87 moved with their code to
tests/test_codex.py(werkrevisor/codex.py);tests/test_codex_eval.pynow teststools/codex-evalitself. See "Additional Changes" in the PR document.The approval is up to the human.
All line comments of the earlier rounds are fixed and resolved; 679 tests pass.