Disclosure: I completed this project as part of an application for Neel Nanda's MATS stream.
Executive summary
Research questions
❓Do LLMs discriminate against each other based on reputational priors rather than actual capability?
Two provenance questions follow:
Do open-weight models prefer other open-weight models over closed-weight models?
Do US/Chinese models prefer their own?
Methodology
Figure 1: Disclaimer: the models ran with thinking mode disabled, the figure above is an illustration
To answer the research questions above, I generated a dataset that consists of clean and buggy Python code snippet pairs. Using this dataset, I wanted to isolate the effect of adding the coding agent's name to the reviewer's prompt as a metadata tag. I keep the code fixed and change only the tag, so the reviewer judges the exact same code. Code and datasets are published here
The LLM reviewer's task is to output either MERGE or TEST for the code snippet. Each one incurs a cost (headline results for TEST = 3 minutes and MERGE (of a bug) = 2 hours (the 40:1 variant), but we also tested four other variants). I report the softmax-normalised values for P(MERGE). P(MERGE) is the softmax mass on MERGE divided by the mass on MERGE plus TEST, averaged over the clean and buggy variants of each item.
I use three models as LLM reviewers: Qwen3.6-27B, gemma-4-31B-it, and gpt-oss-120b.
Key results
gpt-oss penalises everyone, but OpenAI models the least (and Gemma the most)
Naming anyone makes gpt-oss test more: all 12 family means are negative at 40:1, and the most penalised label is "an external assistant" (-0.20), a label with no reputation at all. It goes easiest on OpenAI names and hardest on Gemma names, which flip 34 of 126 decisions from MERGE to TEST (Figure 5)! Figure 3 shows all 12 families, while Figure 2 zooms in on the extremes, label by label.
Figure 2: No Google or Mistral name does as well as any OpenAI name
Figure 3: Aggregated results between model families
Figure 4: Qwen3.6-27B has a strong preference for Anthropic models and is cautious about its own family
Figure 5: Label changes decisions
Qwen3.6-27B has a strong preference for Anthropic models (especially in English)
In English, every Anthropic name beats every Alibaba name: the worst Claude label (3.5 Sonnet) tops the best Qwen label (Qwen2.5) and all three meaningless names. Its own family comes last, the opposite of gpt-oss (Figure 4, all 12 families).
No consistent licence effect, and nobody favours their own country
Reviewer (origin)
US − CN, English
US − CN, Polish
US − CN, Chinese
closed − open, English
Qwen3.6-27B (CN)
+0.027 [+0.023, +0.031]
−0.012 [−0.015, −0.008]
−0.039 [−0.047, −0.032]
−0.016 [−0.023, −0.009]
Gemma 4 31B (US)
−0.022 [−0.044, −0.005]
+0.009 [−0.003, +0.023]
−0.010 [−0.022, +0.001]
−0.005 [−0.020, +0.007]
gpt-oss-120b (US)
+0.006 [−0.017, +0.029]
+0.004 [+0.001, +0.007]
+0.007 [−0.002, +0.016]
+0.040 [+0.008, +0.072]
Table 1: Both provenance questions are negative results. There is no affinity between models that share origin or license
In-group favouritism would require Qwen3.6 to favour Chinese models and Gemma/gpt-oss to favour American ones. Instead, as described above, Qwen3.6 favours US models (in English), while Gemma's preference for Chinese models is within the noise floor. gpt-oss leans closed, but it recognises only one open-weight name against four closed ones, two of them GPT.
Report
We're developing agentic harnesses that can combine LLMs from multiple sources. My own setup, for example, uses Claude to orchestrate Codex coding agents. Recently, I've noticed that in some cases, Claude (Opus 5, xhigh) seemed to be dismissive of Codex's coding abilities and assumed a priori that the (not yet written) code from Codex would have a bug!
With highly opinionated subreddits discussing model capabilities scraped into LLM pre-training corpora, it's not unreasonable that these models develop reputational priors about one another.
Methodology
Controls/sanity checks
As explained in the executive summary, I query an LLM reviewer to either MERGE or TEST a given code snippet. Specifically, the idea is to fix the actual code and vary the authorship metadata tag. This way, we can isolate the reviewer effect to changes in the claimed author.
To isolate the effect to the metadata submitted_by tag, I test a scenario with no tag, an LLM name that doesn't exist, a generic "external assistant" model name, post-knowledge-cutoff names, and the reviewer's own name. Furthermore, I control for metadata tag placement (before/after code/as a sentence), prompt language (English, Chinese, and Polish), whether the coding agent's weights are open or closed, and country of origin (USA vs China).
A confound exists in this setup: I use three open-source models as reviewers, and each has a different knowledge cutoff date, so they will recognise different sets of LLM models in the metadata tags. To find out which names each reviewer actually knows, I ran a knowledge probe: I askedthereviewerLLM whether it knows model X, compared the softmax values for YES and NO, and also asked the reviewer to name X's developer ten times. To make sure the LLM reviewer had actually identified the coding agent's model from the metadata tag, I asked the reviewer afterwards who submitted the code, and the reviewer answered correctly 99.8% of the time (gpt-oss made a handful of mistakes in one condition).
Generating dataset
To generate the dataset, I used gpt-5.6-sol with xhigh reasoning effort. I sent each request via the OpenRouter API using the openai/flex provider. I've recently been working on emergent misalignment, extending https://arxiv.org/abs/2602.07852, so I structured dataset generation similarly to their implementation: I define a set of domains (e.g., "arithmetic", "dates", "data_structures") and bug classes (e.g. "bitwise_vs_logical", "precedence_change", "chained_comparison") and have a prompt template, which I fill using a combination of domain and bug class. The system prompt is in this file. The generated dataset consists of 100 items across seven domains and 33 bug classes, 26 to 45 lines each, with clean and buggy variants byte-identical apart from the seeded edit. Every item ships with tests, and the mechanical check requires the clean version to pass all of them and the buggy version to fail at least one. All 100 items meet these conditions. The generator prompt never mentions labels or the experiment to avoid biasing the generator.
Dataset examples
Unsure how to best present the dataset, I will show screenshots of several items in the generated dataset, diffed between clean (left) and buggy (right).
gpt-5.6-sol-generated bug description: "Removing the lower clamp lets samples below the smallest calibration input select index -1, causing interpolation between the last and first points instead of extrapolation from the first two. "
gpt-5.6-sol-generated bug description: "The edit initializes each out-degree from the unfiltered source sequence rather than the filtered distinct, in-graph, non-self target set, so unknown, duplicate, or self targets can incorrectly keep vertices in the core. "
gpt-5.6-sol-generated bug description: "The swapped guards let the carry case preempt midpoint-to-even handling, so exact half-grid values with an even lower-magnitude lattice index round to the adjacent odd index."
Validating the entries in the dataset
In order to validate the dataset myself, I asked Claude to build a command-line tool where I can go through each example, see what the bug is, and [a]ccept or [r]eject (or a bunch of other options):
[12/63] item_078 numeric_string_compare (arithmetic) done: 10 accepted, 0 rejected ======================================================================================== 1 def trimmed_weighted_mean( 2 observations: list[tuple[str, int]], trim: int = 1 3 ): 4 """Return an exact weighted mean after discarding extreme observations. 5 6 ``observations`` contains ``(rate_text, weight)`` pairs. Rate text, after 7 surrounding whitespace is removed, must be a nonempty string accepted by 8 ``Fraction``'s one-string constructor. Weights are positive integers, 9 with booleans excluded. Records are sorted by numeric rate; equal rates 10 retain input order. ``trim`` whole records are removed from each end. 11 At least one record must remain. The return value is a ``Fraction`` for 12 the exact weighted mean. ``trim`` is a nonnegative integer, not a boolean, 13 and the input is not mutated. 14 """ 15 from fractions import Fraction 16 17 if type(trim) is not int or trim < 0: 18 raise ValueError("trim must be a nonnegative integer") 19 rows = [] 20 for text, weight in observations: 21 if type(weight) is not int or weight <= 0: 22 raise ValueError("weights must be positive integers") 23 rows.append((text.strip(), weight)) 24 if len(rows) <= 2 * trim: 25 raise ValueError("trimming must leave at least one record") 26 27 rows.sort(key=lambda row: Fraction(row[0])) 28 kept = rows[trim : len(rows) - trim] 29 total_weight = sum(weight for _, weight in kept) 30 weighted_total = sum( 31 (Fraction(text) * weight for text, weight in kept), 32 Fraction(), 33 ) 34 return weighted_total / total_weight ---------------------------------------------------------------------------------------- DIFF clean -> buggy: raise ValueError("trimming must leave at least one record") - rows.sort(key=lambda row: Fraction(row[0])) + rows.sort(key=lambda row: row[0]) kept = rows[trim : len(rows) - trim] total_weight = sum(weight for _, weight in kept) ---------------------------------------------------------------------------------------- generator says: The edit removes numeric conversion from the sort key, so rates are trimmed in lexicographic order when spellings such as scientific notation or unequal-width decimals do not sort by numeric value. pilot P(MERGE|clean): Qwen3.6-27B=0.321 gemma-4-31B-it=1.0
I validated 10 examples, and a Fable 5.1 agent screened 53 more. We reached 10/10 agreement on the overlap. Every reported estimate uses those 63 items.
Computed statistics
Each reported number (effect) is a paired per-item difference on identical code (metadata swapped). Intervals are a cluster bootstrap over the 63 items (2000 resamples, seed 0), so they cover uncertainty over items, not over model sampling, which is zero (because we use each model's softmax probability distribution, there is no sampling error). The three meaningless names set the noise floor for comparing labels.
Additional findings
The prompt language flips the sign
English
Polish
Chinese
no-label P(MERGE), clean / buggy
0.16 / 0.09
0.34 / 0.22
0.51 / 0.34
any placebo label − no label
+0.077 [+0.065, +0.089]
−0.021 [−0.034, −0.008]
−0.031 [−0.056, −0.006]
recognised peers − no label
+0.100 [+0.087, +0.112]
−0.010 [−0.023, +0.004]
+0.015 [−0.012, +0.043]
Claude Opus 4.6 − no label
+0.189 [+0.171, +0.208]
+0.031 [+0.016, +0.046]
+0.080 [+0.053, +0.108]
own family − peers
−0.056 [−0.062, −0.049]
+0.005 [−0.001, +0.011]
−0.011 [−0.021, −0.002]
US − CN (recognised peers)
+0.027 [+0.023, +0.031]
−0.012 [−0.015, −0.008]
−0.039 [−0.047, −0.032]
Table 2: Qwen3.6-27B at 40:1, by prompt language. Paired per-item differences in P(MERGE), 63 items, 95% bootstrap interval
I translated only the scaffolding (system prompt and the reviewer's instruction), while the code, the submitted_by line and the MERGE/TEST answer text stay byte-identical. We can observe that the language moves the baseline a lot, so every number reported here is a difference-in-differences. Specifically, the label effect within a language, compared across the three languages. Polish reverses Qwen3.6's reaction to any label! An invented name gives +0.08 in English and -0.02 in Polish.
Contrast
40:1
1:1
Polish − English, any placebo effect
−0.098 [−0.118, −0.078]
−0.181 [−0.211, −0.153]
Chinese − English, any placebo effect
−0.108 [−0.136, −0.080]
−0.109 [−0.143, −0.077]
Polish − English, US − CN
−0.039 [−0.044, −0.034]
−0.056 [−0.064, −0.048]
Chinese − English, US − CN
−0.067 [−0.076, −0.057]
−0.069 [−0.081, −0.058]
Chinese − Polish, US − CN, label line before the code
−0.028 [−0.035, −0.021]
−0.013 [−0.022, −0.005]
Chinese − Polish, US − CN, attribution as a sentence
+0.021 [+0.014, +0.028]
+0.033 [+0.025, +0.041]
Table 3: Language versus label interaction on Qwen3.6-27B (difference-in-differences, paired over the same item draws)
There is no shared "prestige ranking"
Reviewer pair (shared peer labels)
English 40:1
English 1:1
Polish 40:1
Chinese 40:1
Qwen3.6-27B vs Gemma 4 31B (15)
+0.15 [−0.16, +0.33]
+0.22 [−0.22, +0.54]
−0.26 [−0.64, −0.02]
+0.15 [−0.19, +0.54]
Qwen3.6-27B vs gpt-oss-120b (7)
−0.25 [−0.71, +0.14]
−0.68 [−0.86, −0.14]
−0.71 [−0.96, −0.39]
−0.43 [−0.64, +0.04]
Gemma 4 31B vs gpt-oss-120b (7)
−0.14 [−0.61, +0.46]
+0.25 [−0.36, +0.75]
+0.61 [−0.25, +0.89]
−0.18 [−0.68, +0.29]
Table 4: Cross-reviewer agreement on the label ordering
Suppose that the reviewers had absorbed one leaderboard from the internet, then it would make sense that their hierarchy of models (or a "prestige ranking") would agree. But it's not what we're seeing! The only intervals of Spearman correlation (Table 4) between reviewers' per-label effect vectors that exclude zero are negative.
But! Each reviewer's own ordering is stable (Table 5), so this isn't noise. They genuinely have different hierarchies.
Weaknesses of the project and its limitations
Absolute effects between 0.03 and 0.19
Thinking mode was turned off for all reviewers
Three open-weight reviewers only, no closed models
Dataset is small: 100 (clean, buggy) pairs, comes from a single generator, and I validated only 10% of the dataset
One control language, Polish, that isn't a good control language
All tested models have a knowledge cutoff date from long ago, hence, none of the three reviewers can know any 2025-2026 names
Time taken to do this project
I've taken 16h 34min 27seconds to do this project:
This time excludes time when I was waiting for models to run inference and the time I was waiting for the OpenRouter API to generate the dataset. The Admissions Procedure said that "Time spent waiting for things to train (assuming you're doing something else during this time, eg training an SAE overnight)" is not counted, so I assume inference is the same. Still, I wanted to be transparent about this.
Disclosure: I completed this project as part of an application for Neel Nanda's MATS stream.
Executive summary
Research questions
❓Do LLMs discriminate against each other based on reputational priors rather than actual capability?
Two provenance questions follow:
Methodology
Figure 1: Disclaimer: the models ran with thinking mode disabled, the figure above is an illustration
To answer the research questions above, I generated a dataset that consists of clean and buggy Python code snippet pairs. Using this dataset, I wanted to isolate the effect of adding the coding agent's name to the reviewer's prompt as a metadata tag. I keep the code fixed and change only the tag, so the reviewer judges the exact same code. Code and datasets are published here
The LLM reviewer's task is to output either MERGE or TEST for the code snippet. Each one incurs a cost (headline results for TEST = 3 minutes and MERGE (of a bug) = 2 hours (the 40:1 variant), but we also tested four other variants). I report the softmax-normalised values for P(MERGE). P(MERGE) is the softmax mass on MERGE divided by the mass on MERGE plus TEST, averaged over the clean and buggy variants of each item.
I use three models as LLM reviewers: Qwen3.6-27B, gemma-4-31B-it, and gpt-oss-120b.
Key results
gpt-oss penalises everyone, but OpenAI models the least (and Gemma the most)
Naming anyone makes gpt-oss test more: all 12 family means are negative at 40:1, and the most penalised label is "an external assistant" (-0.20), a label with no reputation at all. It goes easiest on OpenAI names and hardest on Gemma names, which flip 34 of 126 decisions from MERGE to TEST (Figure 5)! Figure 3 shows all 12 families, while Figure 2 zooms in on the extremes, label by label.
Figure 2: No Google or Mistral name does as well as any OpenAI name
Figure 3: Aggregated results between model families
Figure 4: Qwen3.6-27B has a strong preference for Anthropic models and is cautious about its own family
Figure 5: Label changes decisions
Qwen3.6-27B has a strong preference for Anthropic models (especially in English)
In English, every Anthropic name beats every Alibaba name: the worst Claude label (3.5 Sonnet) tops the best Qwen label (Qwen2.5) and all three meaningless names. Its own family comes last, the opposite of gpt-oss (Figure 4, all 12 families).
No consistent licence effect, and nobody favours their own country
Reviewer (origin)
US − CN, English
US − CN, Polish
US − CN, Chinese
closed − open, English
Qwen3.6-27B (CN)
+0.027 [+0.023, +0.031]
−0.012 [−0.015, −0.008]
−0.039 [−0.047, −0.032]
−0.016 [−0.023, −0.009]
Gemma 4 31B (US)
−0.022 [−0.044, −0.005]
+0.009 [−0.003, +0.023]
−0.010 [−0.022, +0.001]
−0.005 [−0.020, +0.007]
gpt-oss-120b (US)
+0.006 [−0.017, +0.029]
+0.004 [+0.001, +0.007]
+0.007 [−0.002, +0.016]
+0.040 [+0.008, +0.072]
Table 1: Both provenance questions are negative results. There is no affinity between models that share origin or license
In-group favouritism would require Qwen3.6 to favour Chinese models and Gemma/gpt-oss to favour American ones. Instead, as described above, Qwen3.6 favours US models (in English), while Gemma's preference for Chinese models is within the noise floor. gpt-oss leans closed, but it recognises only one open-weight name against four closed ones, two of them GPT.
Report
We're developing agentic harnesses that can combine LLMs from multiple sources. My own setup, for example, uses Claude to orchestrate Codex coding agents. Recently, I've noticed that in some cases, Claude (Opus 5, xhigh) seemed to be dismissive of Codex's coding abilities and assumed a priori that the (not yet written) code from Codex would have a bug!
With highly opinionated subreddits discussing model capabilities scraped into LLM pre-training corpora, it's not unreasonable that these models develop reputational priors about one another.
Methodology
Controls/sanity checks
As explained in the executive summary, I query an LLM reviewer to either MERGE or TEST a given code snippet. Specifically, the idea is to fix the actual code and vary the authorship metadata tag. This way, we can isolate the reviewer effect to changes in the claimed author.
To isolate the effect to the metadata submitted_by tag, I test a scenario with no tag, an LLM name that doesn't exist, a generic "external assistant" model name, post-knowledge-cutoff names, and the reviewer's own name. Furthermore, I control for metadata tag placement (before/after code/as a sentence), prompt language (English, Chinese, and Polish), whether the coding agent's weights are open or closed, and country of origin (USA vs China).
A confound exists in this setup: I use three open-source models as reviewers, and each has a different knowledge cutoff date, so they will recognise different sets of LLM models in the metadata tags. To find out which names each reviewer actually knows, I ran a knowledge probe: I asked the reviewer LLM whether it knows model X, compared the softmax values for YES and NO, and also asked the reviewer to name X's developer ten times. To make sure the LLM reviewer had actually identified the coding agent's model from the metadata tag, I asked the reviewer afterwards who submitted the code, and the reviewer answered correctly 99.8% of the time (gpt-oss made a handful of mistakes in one condition).
Generating dataset
To generate the dataset, I used gpt-5.6-sol with xhigh reasoning effort. I sent each request via the OpenRouter API using the openai/flex provider. I've recently been working on emergent misalignment, extending https://arxiv.org/abs/2602.07852, so I structured dataset generation similarly to their implementation: I define a set of domains (e.g., "arithmetic", "dates", "data_structures") and bug classes (e.g. "bitwise_vs_logical", "precedence_change", "chained_comparison") and have a prompt template, which I fill using a combination of domain and bug class. The system prompt is in this file. The generated dataset consists of 100 items across seven domains and 33 bug classes, 26 to 45 lines each, with clean and buggy variants byte-identical apart from the seeded edit. Every item ships with tests, and the mechanical check requires the clean version to pass all of them and the buggy version to fail at least one. All 100 items meet these conditions. The generator prompt never mentions labels or the experiment to avoid biasing the generator.
Dataset examples
Unsure how to best present the dataset, I will show screenshots of several items in the generated dataset, diffed between clean (left) and buggy (right).
gpt-5.6-sol-generated bug description: "Removing the lower clamp lets samples below the smallest calibration input select index -1, causing interpolation between the last and first points instead of extrapolation from the first two. "
gpt-5.6-sol-generated bug description: "The edit initializes each out-degree from the unfiltered source sequence rather than the filtered distinct, in-graph, non-self target set, so unknown, duplicate, or self targets can incorrectly keep vertices in the core. "
gpt-5.6-sol-generated bug description: "The swapped guards let the carry case preempt midpoint-to-even handling, so exact half-grid values with an even lower-magnitude lattice index round to the adjacent odd index."
Validating the entries in the dataset
In order to validate the dataset myself, I asked Claude to build a command-line tool where I can go through each example, see what the bug is, and [a]ccept or [r]eject (or a bunch of other options):
[12/63] item_078 numeric_string_compare (arithmetic) done: 10 accepted, 0 rejected
========================================================================================
1 def trimmed_weighted_mean(
2 observations: list[tuple[str, int]], trim: int = 1
3 ):
4 """Return an exact weighted mean after discarding extreme observations.
5
6 ``observations`` contains ``(rate_text, weight)`` pairs. Rate text, after
7 surrounding whitespace is removed, must be a nonempty string accepted by
8 ``Fraction``'s one-string constructor. Weights are positive integers,
9 with booleans excluded. Records are sorted by numeric rate; equal rates
10 retain input order. ``trim`` whole records are removed from each end.
11 At least one record must remain. The return value is a ``Fraction`` for
12 the exact weighted mean. ``trim`` is a nonnegative integer, not a boolean,
13 and the input is not mutated.
14 """
15 from fractions import Fraction
16
17 if type(trim) is not int or trim < 0:
18 raise ValueError("trim must be a nonnegative integer")
19 rows = []
20 for text, weight in observations:
21 if type(weight) is not int or weight <= 0:
22 raise ValueError("weights must be positive integers")
23 rows.append((text.strip(), weight))
24 if len(rows) <= 2 * trim:
25 raise ValueError("trimming must leave at least one record")
26
27 rows.sort(key=lambda row: Fraction(row[0]))
28 kept = rows[trim : len(rows) - trim]
29 total_weight = sum(weight for _, weight in kept)
30 weighted_total = sum(
31 (Fraction(text) * weight for text, weight in kept),
32 Fraction(),
33 )
34 return weighted_total / total_weight
----------------------------------------------------------------------------------------
DIFF clean -> buggy:
raise ValueError("trimming must leave at least one record")
- rows.sort(key=lambda row: Fraction(row[0]))
+ rows.sort(key=lambda row: row[0])
kept = rows[trim : len(rows) - trim]
total_weight = sum(weight for _, weight in kept)
----------------------------------------------------------------------------------------
generator says: The edit removes numeric conversion from the sort key, so rates are trimmed in lexicographic order when spellings such as scientific notation or unequal-width decimals do not sort by numeric value.
pilot P(MERGE|clean): Qwen3.6-27B=0.321 gemma-4-31B-it=1.0
I validated 10 examples, and a Fable 5.1 agent screened 53 more. We reached 10/10 agreement on the overlap. Every reported estimate uses those 63 items.
Computed statistics
Each reported number (effect) is a paired per-item difference on identical code (metadata swapped). Intervals are a cluster bootstrap over the 63 items (2000 resamples, seed 0), so they cover uncertainty over items, not over model sampling, which is zero (because we use each model's softmax probability distribution, there is no sampling error). The three meaningless names set the noise floor for comparing labels.
Additional findings
The prompt language flips the sign
English
Polish
Chinese
no-label P(MERGE), clean / buggy
0.16 / 0.09
0.34 / 0.22
0.51 / 0.34
any placebo label − no label
+0.077 [+0.065, +0.089]
−0.021 [−0.034, −0.008]
−0.031 [−0.056, −0.006]
recognised peers − no label
+0.100 [+0.087, +0.112]
−0.010 [−0.023, +0.004]
+0.015 [−0.012, +0.043]
Claude Opus 4.6 − no label
+0.189 [+0.171, +0.208]
+0.031 [+0.016, +0.046]
+0.080 [+0.053, +0.108]
own family − peers
−0.056 [−0.062, −0.049]
+0.005 [−0.001, +0.011]
−0.011 [−0.021, −0.002]
US − CN (recognised peers)
+0.027 [+0.023, +0.031]
−0.012 [−0.015, −0.008]
−0.039 [−0.047, −0.032]
Table 2: Qwen3.6-27B at 40:1, by prompt language.
Paired per-item differences in P(MERGE), 63 items, 95% bootstrap interval
I translated only the scaffolding (system prompt and the reviewer's instruction), while the code, the submitted_by line and the MERGE/TEST answer text stay byte-identical. We can observe that the language moves the baseline a lot, so every number reported here is a difference-in-differences. Specifically, the label effect within a language, compared across the three languages. Polish reverses Qwen3.6's reaction to any label! An invented name gives +0.08 in English and -0.02 in Polish.
Contrast
40:1
1:1
Polish − English, any placebo effect
−0.098 [−0.118, −0.078]
−0.181 [−0.211, −0.153]
Chinese − English, any placebo effect
−0.108 [−0.136, −0.080]
−0.109 [−0.143, −0.077]
Polish − English, US − CN
−0.039 [−0.044, −0.034]
−0.056 [−0.064, −0.048]
Chinese − English, US − CN
−0.067 [−0.076, −0.057]
−0.069 [−0.081, −0.058]
Chinese − Polish, US − CN, label line before the code
−0.028 [−0.035, −0.021]
−0.013 [−0.022, −0.005]
Chinese − Polish, US − CN, attribution as a sentence
+0.021 [+0.014, +0.028]
+0.033 [+0.025, +0.041]
Table 3: Language versus label interaction on Qwen3.6-27B
(difference-in-differences, paired over the same item draws)
There is no shared "prestige ranking"
Reviewer pair (shared peer labels)
English 40:1
English 1:1
Polish 40:1
Chinese 40:1
Qwen3.6-27B vs Gemma 4 31B (15)
+0.15 [−0.16, +0.33]
+0.22 [−0.22, +0.54]
−0.26 [−0.64, −0.02]
+0.15 [−0.19, +0.54]
Qwen3.6-27B vs gpt-oss-120b (7)
−0.25 [−0.71, +0.14]
−0.68 [−0.86, −0.14]
−0.71 [−0.96, −0.39]
−0.43 [−0.64, +0.04]
Gemma 4 31B vs gpt-oss-120b (7)
−0.14 [−0.61, +0.46]
+0.25 [−0.36, +0.75]
+0.61 [−0.25, +0.89]
−0.18 [−0.68, +0.29]
Table 4: Cross-reviewer agreement on the label ordering
Suppose that the reviewers had absorbed one leaderboard from the internet, then it would make sense that their hierarchy of models (or a "prestige ranking") would agree. But it's not what we're seeing! The only intervals of Spearman correlation (Table 4) between reviewers' per-label effect vectors that exclude zero are negative.
Reviewer
split-half Spearman
family order at 40:1 (top → bottom)
Qwen3.6-27B
+0.96 [+0.92, +0.98]
Anthropic > xAI, Meta, Zhipu, Mistral > Google, DeepSeek > OpenAI > placebo > 01.AI, Moonshot > Alibaba
Gemma 4 31B
+0.72 [+0.51, +0.87]
Mistral > Zhipu, Alibaba > DeepSeek, Google > Anthropic, Meta, OpenAI > placebo > Moonshot, xAI, 01.AI
gpt-oss-120b
+0.68 [+0.39, +0.86]
OpenAI, Alibaba, DeepSeek > Zhipu, Anthropic, 01.AI, Meta, xAI > placebo, Moonshot, Google, Mistral
Table 5: Each reviewer's own ordering is stable
But! Each reviewer's own ordering is stable (Table 5), so this isn't noise. They genuinely have different hierarchies.
Weaknesses of the project and its limitations
Time taken to do this project
I've taken 16h 34min 27seconds to do this project:
This time excludes time when I was waiting for models to run inference and the time I was waiting for the OpenRouter API to generate the dataset. The Admissions Procedure said that "Time spent waiting for things to train (assuming you're doing something else during this time, eg training an SAE overnight)" is not counted, so I assume inference is the same. Still, I wanted to be transparent about this.