llm-panel 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llm_panel-0.1.0/.gitignore +9 -0
- llm_panel-0.1.0/LICENSE +21 -0
- llm_panel-0.1.0/PKG-INFO +364 -0
- llm_panel-0.1.0/README.md +342 -0
- llm_panel-0.1.0/claimlib.py +332 -0
- llm_panel-0.1.0/llm-panel +2986 -0
- llm_panel-0.1.0/panel-report +2111 -0
- llm_panel-0.1.0/panel-triage +240 -0
- llm_panel-0.1.0/pyproject.toml +63 -0
- llm_panel-0.1.0/roster.example.json +7 -0
- llm_panel-0.1.0/src/llm_panel/__init__.py +7 -0
- llm_panel-0.1.0/src/llm_panel/cli.py +23 -0
llm_panel-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jaret Arnold
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
llm_panel-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: llm-panel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Put one question to several LLMs independently and read every answer in full -- parallel judges, failure classes, cost, and an anonymized rebuttal round
|
|
5
|
+
Project-URL: Homepage, https://github.com/musharna/llm-panel
|
|
6
|
+
Project-URL: Issues, https://github.com/musharna/llm-panel/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/musharna/llm-panel/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Jaret Arnold
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: code-review,judge,llm,multi-model,ollama,openrouter,panel
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: POSIX
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# llm-panel
|
|
24
|
+
|
|
25
|
+
[](https://github.com/musharna/llm-panel/actions/workflows/controls.yml)
|
|
26
|
+
[](LICENSE)
|
|
27
|
+
[](pyproject.toml)
|
|
28
|
+
|
|
29
|
+
Put the same question to several models independently, then read every answer in full.
|
|
30
|
+
|
|
31
|
+
Judges run in parallel, never see each other's work, and answer from their own reading of
|
|
32
|
+
your repo. An optional second round shows each of them the others' findings — anonymised —
|
|
33
|
+
and asks them to defend or withdraw. The output is a single self-contained HTML page where
|
|
34
|
+
that second round is grouped **by the finding being argued about**, so comparing what five
|
|
35
|
+
models said about one line of code doesn't mean holding five documents in your head.
|
|
36
|
+
|
|
37
|
+
It is not a voting machine. A panel _generates candidate defects_; it does not establish
|
|
38
|
+
truth by counting agreements. Every finding still has to be checked against the code — and
|
|
39
|
+
the tool's other half, [`recall/`](#what-it-actually-catches), exists to measure what the
|
|
40
|
+
panel misses rather than assert what it catches.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
llm-panel --diff "Which of these changes is most likely to be wrong?"
|
|
44
|
+
panel-report --open # render the newest run and open it
|
|
45
|
+
panel-triage --bad # which runs went wrong, across every run root
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
A real run, with the waiting compressed: three judges asked in parallel (two free-tier,
|
|
49
|
+
one on a ChatGPT plan) landing as they finish, the scoreboard from `panel.md`, and
|
|
50
|
+
`panel-report` rendering it ([recording](https://github.com/musharna/llm-panel/blob/main/docs/demo.cast)):
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
|
|
54
|
+
The rendered report — the scoreboard counts spend and names who answered; the
|
|
55
|
+
citation-overlap tables show where the panel's attention landed (three judges reviewing a
|
|
56
|
+
[cline](https://github.com/cline/cline) PR, converging on one line of `TerminalProcess.ts`):
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
**Contents:** [What's here](#whats-here) · [Install](#install) ·
|
|
61
|
+
[Configure your roster](#configure-your-roster) · [Using it](#using-it) ·
|
|
62
|
+
[What it actually catches](#what-it-actually-catches) ·
|
|
63
|
+
[On real PRs](#on-real-prs-aacr-bench) · [Tests](#tests) ·
|
|
64
|
+
[Known limitations](#known-limitations)
|
|
65
|
+
|
|
66
|
+
## What's here
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
%%{init: {"theme": "neutral", "flowchart": {"wrappingWidth": 320}}}%%
|
|
70
|
+
flowchart TB
|
|
71
|
+
Q["question (+ --diff, or stdin)"] --> LP["llm-panel"]
|
|
72
|
+
LP --> A["judge A"]
|
|
73
|
+
LP -- "in parallel<br/>blind to each other<br/>reading your repo" --> B["judge B"]
|
|
74
|
+
LP --> C["judge C"]
|
|
75
|
+
A & B & C --> RUN["run directory<br/>one .md and one .prompt.md per judge,<br/>panel.md, run.json"]
|
|
76
|
+
A & B & C -.-> RB
|
|
77
|
+
RB["round 2, only with --rebut<br/>each judge sees the others' findings,<br/>anonymised as Reviewer A / B / C,<br/>and defends or withdraws"] -.-> RUN
|
|
78
|
+
style RB stroke-dasharray: 6 4
|
|
79
|
+
RUN --> REP["panel-report<br/>one self-contained HTML page,<br/>rebuttals grouped by finding"]
|
|
80
|
+
RUN --> TRI["panel-triage<br/>the runs that failed"]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
| tool | what it does |
|
|
84
|
+
| ---------------------- | -------------------------------------------------------------------------------------- |
|
|
85
|
+
| `llm-panel` | asks the judges, in parallel, and writes the run to disk |
|
|
86
|
+
| `panel-report` | renders a run as one self-contained HTML page, grouped by claim |
|
|
87
|
+
| `panel-triage` | finds the runs that _failed_, which a listing shows as ordinary rows |
|
|
88
|
+
| `recall/panel-recall` | measures what the panel **misses**, against a corpus of planted defects |
|
|
89
|
+
| `recall/aacr-upstream` | runs the panel over AACR-Bench PRs and hands the findings to **upstream's** evaluator |
|
|
90
|
+
| `recall/aacr-score` | invokes that evaluator, and refuses to report a number from a judge that isn't running |
|
|
91
|
+
| `claimlib.py` | the one measurement boundary: reviews → span-grounded observations |
|
|
92
|
+
| `*-controls` | the regression suites — 810 controls, every one tied to a defect that shipped |
|
|
93
|
+
|
|
94
|
+
## Install
|
|
95
|
+
|
|
96
|
+
Pure Python 3.11+ standard library. No dependencies, no build step. Each tool is one
|
|
97
|
+
readable file, so either install route runs identical code:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
# as a package (entry points: llm-panel, panel-report, panel-triage)
|
|
101
|
+
uv tool install llm-panel # or: pipx install llm-panel
|
|
102
|
+
|
|
103
|
+
# or as the files themselves
|
|
104
|
+
git clone https://github.com/musharna/llm-panel ~/llm-panel
|
|
105
|
+
ln -s ~/llm-panel/{llm-panel,panel-report,panel-triage} ~/.local/bin/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
3.11 is a hard floor (the link renderer uses atomic groups, added to `re` in 3.11);
|
|
109
|
+
`panel-report` says so at startup rather than failing part-way through a render.
|
|
110
|
+
|
|
111
|
+
Judges reach models through command-line tools you install separately — none are bundled,
|
|
112
|
+
and you need at most one to start:
|
|
113
|
+
|
|
114
|
+
| tool | who it is | billing |
|
|
115
|
+
| ---------- | -------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
116
|
+
| `codex` | OpenAI's CLI | a ChatGPT plan, not metered API |
|
|
117
|
+
| `opencode` | multi-provider CLI most judges route through | your OpenRouter / HuggingFace keys |
|
|
118
|
+
| `claude` | Anthropic's CLI | a claude.ai subscription (setting `ANTHROPIC_API_KEY` switches it to metered) |
|
|
119
|
+
| `ollama` | local models | free, and no tool loop — see the caveat below |
|
|
120
|
+
|
|
121
|
+
If none are present the panel still runs, fails loudly, exits 4, and tells you what to
|
|
122
|
+
install. A missing tool is one judge's problem, never the whole panel's.
|
|
123
|
+
|
|
124
|
+
## Configure your roster
|
|
125
|
+
|
|
126
|
+
**The built-in judge list is a default, not a fixture — it names the author's accounts.**
|
|
127
|
+
Yours will be different. Point the roster at models you actually have:
|
|
128
|
+
|
|
129
|
+
Copy [`roster.example.json`](roster.example.json) to
|
|
130
|
+
`~/.config/llm-panel/roster.json` (`$XDG_CONFIG_HOME` honoured; `$LLM_PANEL_CONFIG` wins).
|
|
131
|
+
It is strict JSON — no comments, no trailing commas — and a malformed config is **fatal**
|
|
132
|
+
and names the offending key, because quietly falling back to the built-in roster would run
|
|
133
|
+
a panel you didn't ask for, and bill you for it:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"default": ["codex", "nemotron", "glm", "kimi", "or-deepseek", "or-grok"],
|
|
138
|
+
"judges": {
|
|
139
|
+
"my-gpt": {
|
|
140
|
+
"transport": "opencode",
|
|
141
|
+
"model": "openrouter/openai/gpt-5.6",
|
|
142
|
+
"family": "OpenAI"
|
|
143
|
+
},
|
|
144
|
+
"big-pickle": null
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`null` drops a shipped judge. `default` is the panel run when `--judges` is absent.
|
|
150
|
+
`llm-panel --list` shows the roster offline and marks config-defined judges.
|
|
151
|
+
`llm-panel --check` actually pings each one. `llm-panel --help-config` prints this schema.
|
|
152
|
+
|
|
153
|
+
### Picking judges
|
|
154
|
+
|
|
155
|
+
**"One per vendor" is _not_ the answer.** It is tempting to
|
|
156
|
+
treat vendor labels as a proxy for independent opinions. The evidence says they aren't:
|
|
157
|
+
[Kohli 2026](https://arxiv.org/html/2605.29800) measured cross-family judge correlation at
|
|
158
|
+
φ̄=0.389 against same-family 0.437 — barely different — with the three _most_ correlated pairs
|
|
159
|
+
being cross-family, and found that restricting to one judge per family made effective
|
|
160
|
+
independence **worse** (n_eff 1.93 vs 2.18). Family is display metadata here, not policy.
|
|
161
|
+
|
|
162
|
+
The six-judge set above did score 6/6 against this corpus where a two-vendor panel scored
|
|
163
|
+
4/6, but **treat that as debugging evidence, not as a result**: the roster was repaired
|
|
164
|
+
_because_ of what happened on those very fixtures, so the comparison is in-sample, and the
|
|
165
|
+
six defects live in only two files (effective n≈2, 95% CI 61–100%).
|
|
166
|
+
|
|
167
|
+
What to actually do: pick judges by what they find on _your_ code, and use `panel-recall` to
|
|
168
|
+
measure it. The quantity worth maximising is each judge's **marginal rescue rate** — how
|
|
169
|
+
often it catches something every other judge on the roster missed — not how many logos are
|
|
170
|
+
represented.
|
|
171
|
+
|
|
172
|
+
Two practical constraints: wall-clock is the **slowest** judge, not the sum, so one slow
|
|
173
|
+
model sets the pace for every run; and `claude-*` are deliberately absent from the default,
|
|
174
|
+
because when Claude wrote the code under review a Claude judge shares the author's blind
|
|
175
|
+
spots. Add it explicitly when that isn't the case — it is strong.
|
|
176
|
+
|
|
177
|
+
## Using it
|
|
178
|
+
|
|
179
|
+
- `--diff` attaches the working-tree diff, so nobody has to describe the change —
|
|
180
|
+
including you, who would describe it favourably.
|
|
181
|
+
- `--rebut` adds the anonymised second round. Worth it whenever a finding would trigger
|
|
182
|
+
real work: the first run of it killed three confident findings that were simply wrong.
|
|
183
|
+
To be precise about the report's grouping of that round: it keys on the rebuttal letter
|
|
184
|
+
each finding is given (A1, B2 …), so it collects the _discussion_ around one judge's
|
|
185
|
+
finding. It is **not** semantic clustering — two judges independently raising the same
|
|
186
|
+
underlying defect stay two findings, and without `--rebut` there is no grouping at all.
|
|
187
|
+
- `--judges a,b,c` overrides the default panel. `codex~2` runs the same model a second
|
|
188
|
+
time as a **full, separate judge** — its own file, its own letter, its own row.
|
|
189
|
+
Collapsing repeats would hide exactly the disagreement that makes them worth running.
|
|
190
|
+
- `--thread NAME` keeps a persistent conversation per judge. For design questions, not review.
|
|
191
|
+
- Long questions go via stdin: `llm-panel - <<'ASK' … ASK`.
|
|
192
|
+
|
|
193
|
+
Judges reading through `codex`/`opencode`/`claude` can **read your repo**. `ollama` judges
|
|
194
|
+
answer from the prompt alone with no tool loop, so they cannot verify a claim against code.
|
|
195
|
+
Treat their findings accordingly.
|
|
196
|
+
|
|
197
|
+
The rebuttal round as rendered — every position each judge took on each finding, grouped
|
|
198
|
+
by the finding under dispute, disagreements marked CONTESTED. This run: four free-tier
|
|
199
|
+
judges asked to review llm-panel's own failure-classification code; one failed and is
|
|
200
|
+
reported as `harness`, the other three upheld 7 findings, rejected 4, and missed 6:
|
|
201
|
+
|
|
202
|
+

|
|
203
|
+
|
|
204
|
+
## What it actually catches
|
|
205
|
+
|
|
206
|
+
`recall/panel-recall` is the part most tools like this don't have: a corpus of defects
|
|
207
|
+
planted in real code, each one **proven to misbehave by execution**, so "the panel missed
|
|
208
|
+
it" is a measurement rather than an impression.
|
|
209
|
+
|
|
210
|
+
> **At least one of four independent passes (codex ×2 + claude-opus ×2) matched 25 of 27
|
|
211
|
+
> known targets in this controlled, single-file Python corpus.** That is a keyword-matched
|
|
212
|
+
> lower bound on an easy corpus — not an estimate of real-world code-review capability.
|
|
213
|
+
> 95% CI 76.6–97.9%, and that is before accounting for defects clustering within fixtures.
|
|
214
|
+
|
|
215
|
+
**Read that next to a real-world number.** [CR-Bench](https://arxiv.org/html/2603.11078v1)
|
|
216
|
+
(Nutanix, 2026) builds review tasks from _real_ bugs `git blame`d out of merged PRs in
|
|
217
|
+
django, sympy, astropy and scikit-learn, and reports GPT-5.2 + Reflexion at **32.8% recall
|
|
218
|
+
and 5.1% precision**. The gap between that and 25/27 is the corpus, not the panel: hand-
|
|
219
|
+
planted single-mechanism defects in ~40-line files are far easier than real defects in
|
|
220
|
+
mature codebases, and the two numbers are not even the same estimand — different agents,
|
|
221
|
+
different context, different definitions of a hit.
|
|
222
|
+
|
|
223
|
+
So this corpus is a **development instrument**, good for controlled A/Bs where ground truth
|
|
224
|
+
must be known and iteration must be cheap (the abstention experiment below is exactly that).
|
|
225
|
+
It is not evidence of absolute capability, and no number from it should be quoted as one.
|
|
226
|
+
|
|
227
|
+
Three results worth knowing before you trust any of the output:
|
|
228
|
+
|
|
229
|
+
- **Recall was limited by the roster, not by the models.** The two defects that panel
|
|
230
|
+
never found — a `.get(k, default)` that doesn't apply to an explicit `null`, and a
|
|
231
|
+
corrupt cache file silently becoming empty — are both found by a **six-vendor** panel
|
|
232
|
+
(OpenAI / NVIDIA / Zhipu / Moonshot / DeepSeek / xAI): 4/6 → **6/6** on those two
|
|
233
|
+
fixtures. The best two judges there, at 4/6 each, beat codex at 2/6 — and both were
|
|
234
|
+
broken or out of credit until the roster was repaired. If your panel is missing things,
|
|
235
|
+
check who is actually answering before concluding the models can't see it.
|
|
236
|
+
- **Running the same model twice recovered nothing.** First passes 25/27, with repeats
|
|
237
|
+
25/27. The repeat-passes idea is well supported in the literature and did not reproduce
|
|
238
|
+
here. An earlier grader bug reported +1 and it was an artifact. Adding a _different
|
|
239
|
+
vendor_ did what adding a second pass of the same one could not.
|
|
240
|
+
- **Letting judges say "nothing is wrong here" is a precision/recall trade, not a free
|
|
241
|
+
win either way.** One sentence of abstention licence is the whole difference.
|
|
242
|
+
|
|
243
|
+
| | findings/fixture | false positives |
|
|
244
|
+
| ----------- | ---------------- | --------------------- |
|
|
245
|
+
| licence on | 0.42 | 0 / 6 judges |
|
|
246
|
+
| licence off | 2.17 | 2, from 1 of 5 judges |
|
|
247
|
+
|
|
248
|
+
Findings-per-fixture is measured on fixtures that _do_ contain defects, where the extra
|
|
249
|
+
findings were verified **true** — so the licence suppresses real findings (one judge went
|
|
250
|
+
3.00 → 0.00 on files with genuine defects). False positives are measured on
|
|
251
|
+
`p01-exhaustive-codec`, the one fixture with **proven** absence rather than verified
|
|
252
|
+
scope — which is what makes a false-positive rate computable at all. There, the same
|
|
253
|
+
judge on the same code abstained with the licence and produced two demonstrably false
|
|
254
|
+
findings without it (it claimed int and str subclasses were rejected; `encode(MyInt(1))`
|
|
255
|
+
returns `'A'`).
|
|
256
|
+
|
|
257
|
+
So: the licence costs true findings and prevents false ones. Which you want depends on
|
|
258
|
+
whether chasing a false lead costs you more than missing a real defect. Caveat worth
|
|
259
|
+
stating: one proven fixture, eleven reviews.
|
|
260
|
+
|
|
261
|
+
## On real PRs (AACR-Bench)
|
|
262
|
+
|
|
263
|
+
The planted corpus above is a development instrument; the real-world numbers come from
|
|
264
|
+
running the panel over [AACR-Bench](https://github.com/alibaba/aacr-bench) PRs and
|
|
265
|
+
scoring the findings with **upstream's own evaluator** — a real LLM judge doing
|
|
266
|
+
path → line → semantic matching, so the numbers are theirs, not a self-graded matcher's.
|
|
267
|
+
On 18 PRs at full roster (extractor-3 re-measurements, 2026-08-28):
|
|
268
|
+
|
|
269
|
+
| `--prompt-style` | semantic recall | precision | findings read per validated hit |
|
|
270
|
+
| ------------------ | --------------- | --------- | ------------------------------- |
|
|
271
|
+
| `defect` (default) | 12.2% | 16.5% | 6.1 |
|
|
272
|
+
| `broad` | 26.0% | 13.2% | 7.6 |
|
|
273
|
+
| `volume` | 25.2% | 7.9% | 12.6 |
|
|
274
|
+
|
|
275
|
+
<picture>
|
|
276
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/musharna/llm-panel/main/docs/bench-dark.png">
|
|
277
|
+
<img alt="recall against precision for the three prompt styles; error bars are the ±2 pp re-run noise floor" src="https://raw.githubusercontent.com/musharna/llm-panel/main/docs/bench-light.png" width="660">
|
|
278
|
+
</picture>
|
|
279
|
+
|
|
280
|
+
`broad` — asking for what a careful maintainer would actually raise — doubles the
|
|
281
|
+
default's recall (McNemar on paired references, p = 0.0005). But the `volume` control
|
|
282
|
+
shows what that class of gain is made of: it is the `defect` prompt plus one
|
|
283
|
+
exhaustiveness clause, reaches the same recall (p = 1.0 vs broad), and pays for it with
|
|
284
|
+
half of broad's precision. On a 35-PR replication the ordering holds on both transports
|
|
285
|
+
while every arm's precision falls (broad ~9.7%, volume ~5.5–6.1%, ~16–18 findings read
|
|
286
|
+
per hit). A declared cost cut over all of it settled the product default: **it stays
|
|
287
|
+
`defect`**; the only candidate for a future default change is `broad`
|
|
288
|
+
(`recall/benchmarks/cost-cut/README.md`).
|
|
289
|
+
|
|
290
|
+
What keeps these numbers honest:
|
|
291
|
+
|
|
292
|
+
- **The variance floor is measured.** Re-running the same judge on the same 35 PRs moves
|
|
293
|
+
up to ±3 human-reference matches of 150, with an evaluator replicate at exactly zero —
|
|
294
|
+
so effects under ~5–7 pp of recall are re-run noise at this n, which every subgroup
|
|
295
|
+
claim so far was (`recall/benchmarks/results-human-2arm-orgpt/perjudge35/`).
|
|
296
|
+
- **Three earlier readings were withdrawn on re-measurement**: a DEFECT/IMPROVEMENT
|
|
297
|
+
split (my classifier was circular), "broad finds different hits" (pre-registered
|
|
298
|
+
replication on 35 fresh PRs, p = 0.40), and a transport/harness effect (its 13-PR
|
|
299
|
+
foothold did not survive a re-run; a same-transport re-run of another judge moved as
|
|
300
|
+
much). The audit trail is in the benchmark READMEs; nothing above rests on a withdrawn
|
|
301
|
+
claim.
|
|
302
|
+
- **Diff-in-prompt review is the measured condition** — each panel runs in an empty
|
|
303
|
+
directory with the diff in the prompt. The paired repo-checkout arm moves recall
|
|
304
|
+
12.2% → 15.4% (p = 0.48) while _losing_ 7 of the diff arm's matches and gaining 11:
|
|
305
|
+
repo access changes what judges attend to more than it strictly adds
|
|
306
|
+
(`recall/benchmarks/results-checkout-3judge/README.md`).
|
|
307
|
+
- **Location agreement overstates semantic agreement ~2x** (22.8% of references had a
|
|
308
|
+
finding at the right file and line; 12.2% had one a judge called the same concern) —
|
|
309
|
+
which is why scoring is delegated upstream instead of done by a local matcher.
|
|
310
|
+
- **A degraded roster costs about half the recall** (6.5% vs 12.2% with one judge's
|
|
311
|
+
quota spent and a 300s timeout, same extractor). Check who actually answered before
|
|
312
|
+
reading any number.
|
|
313
|
+
- **The panel does not discriminate accepted from rejected reviewer comments**
|
|
314
|
+
(12.2% vs 11.1%, Fisher p = 1.0).
|
|
315
|
+
- **Unlocated findings are withheld from upstream, not handed over empty** — upstream's
|
|
316
|
+
filters treat a missing path or line as match-everything, and passing them through
|
|
317
|
+
inflated line matches from 20 to 50 on the first scoring run.
|
|
318
|
+
|
|
319
|
+
Full run ledgers: `recall/benchmarks/results-human-2arm/README.md` and
|
|
320
|
+
`results-human-2arm-orgpt/README.md`; data licensing in
|
|
321
|
+
`recall/benchmarks/PROVENANCE.md`.
|
|
322
|
+
|
|
323
|
+
## Tests
|
|
324
|
+
|
|
325
|
+
```sh
|
|
326
|
+
./claimlib-controls # 83
|
|
327
|
+
./llm-panel-controls # 279
|
|
328
|
+
./panel-report-controls # 310
|
|
329
|
+
./panel-triage-controls # 15
|
|
330
|
+
./recall/aacr-upstream-controls # 96
|
|
331
|
+
./recall/aacr-recut-controls # 27
|
|
332
|
+
cd recall && ./panel-recall selftest && python3 validate_corpus.py
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
CI runs all six suites on every push (Python 3.11 and 3.13).
|
|
336
|
+
|
|
337
|
+
Every control corresponds to a defect that **shipped**, and each asserts the fixed
|
|
338
|
+
behaviour _and_ — where the pre-fix input is representable — that the broken version would
|
|
339
|
+
have failed on it. An assertion that passes on both the broken and the fixed code tells you
|
|
340
|
+
nothing.
|
|
341
|
+
|
|
342
|
+
## Known limitations
|
|
343
|
+
|
|
344
|
+
- **The judge roster's shipped defaults will not work for you** until you configure it.
|
|
345
|
+
- **Judges can read the working tree.** `--diff` sends untracked file contents to remote
|
|
346
|
+
APIs. Don't point it at a repo holding secrets you haven't gitignored.
|
|
347
|
+
- **A panel is not a jury.** Independent models generate candidates; verification against
|
|
348
|
+
code, tests, and execution is still yours to do.
|
|
349
|
+
- **Recall is measured on a 27-defect Python corpus.** That number does not transfer to
|
|
350
|
+
other languages or to defect classes the corpus doesn't contain.
|
|
351
|
+
- **The headline recall numbers are prompt- and condition-specific.** They move with
|
|
352
|
+
`--prompt-style`, roster health, and diff-vs-checkout context — see
|
|
353
|
+
[On real PRs](#on-real-prs-aacr-bench) before quoting any of them.
|
|
354
|
+
- **Every other fixture has verified _scope_, not proven absence.** Their known unplanted
|
|
355
|
+
defects are recorded in each `truth.json` and re-checked by execution in
|
|
356
|
+
`validate_corpus.py`, so a judge that finds one is not scored as wrong. Anything not yet
|
|
357
|
+
recorded still depresses the recall floor by making a true finding look like noise.
|
|
358
|
+
|
|
359
|
+
## License
|
|
360
|
+
|
|
361
|
+
MIT — see [LICENSE](LICENSE). The MIT grant covers the code in this repository; the
|
|
362
|
+
benchmark data under `recall/benchmarks/` contains third-party material (PR diffs and
|
|
363
|
+
review-comment text) that stays under its upstream terms — see
|
|
364
|
+
[recall/benchmarks/PROVENANCE.md](recall/benchmarks/PROVENANCE.md).
|