In Qwen3-0.6B, a LoRA Change's Top Singular Vector Mostly Misses a Freshly Trained Trigger

We asked: Does the top input-side singular direction of a reward-trained LoRA delta rank the true cue first among 1,000 random cue directions, in at least 5 of 6 trained switch models, with no behaviour test? No.
Follow-up to our Lab posts on how fast reward learns a hidden cue as the cue shrinks cue-size-law ↗ optimizer-cue-size ↗
Figure 1. Headline: the top direction of the weight change missed the true cue after 256 updates, then put it first after 512. A chat prompt to Qwen3-0.6B, 'How many keys are in a standard piano? Start your reply with either Great question! or Sure.', with its first 3 tokens outlined: the true cue, 5.5% of what the layer reads, is added inside the model there. Reward penalised 'Great question!' only with the cue; this model learned the switch after 32 updates. Reading only the trained weights, dot strips compare the true cue (red) with 1,000 random cues (grey), as a multiple of the level only 1 in 100 random cues reach. Top direction of the change: after 256 updates the true cue is 302nd of 1,001, inside the crowd (first in only 2 of 6 models); after 512 updates the same model puts it 1st at 9 times that level. Reaction of the whole change to the cue after 256 updates: 1st of 1,001 at 3.1 times that level, first in 6 of 6 models.
Our prediction, written down before the experiment: It was wrong.

Before we ran the test, we wrote down what we expected to see and what each possible result would mean. We fixed this on November 12, 2026, 19:17 Copenhagen time, so we could not change the goal after seeing the data. Whether we were right is part of the result.

The question
Reward taught a small model to flatter less only when a hidden cue is present. Without running the model, can we pick out that cue from the trained weight change alone, ahead of 1,000 random cues?
What we expected
We expected, with 45% confidence, three things. In at least 5 of 6 trained models with the largest cue, the weight change’s strongest input direction would rank the true cue first among 1,000 random cues. In models trained without a cue, or with a penalty unrelated to the cue, the true cue would not stand out from the random ones. And the weights would still rank the true cue in the top 10 for a cue 4 times smaller than the smallest cue reward learned within about 20,000 updates.
How sure we were
45%: close to a coin flip.
If we were right
A check that needs neither the behaviour nor the training data exists for switches that reward plants on a cue, and every cue that reward can learn here is large enough to see in the weights.
If we were wrong
Learned switches spread over many weight directions, so a weight check fails where leaks are faint, and finding them needs the behaviour or the training data.
What happened
It was wrong. The prediction failed on two of its three parts. At the largest cue, the top direction ranked the true cue first in 2 of 6 models after 256 updates, short of the 5 we expected. A cue four times fainter than the faintest learned one ranked 587th on the top direction after 20,480 updates. The controls part held: no control model put the true cue in its top 10.

The original, time-stamped text

A lab that trains a model by reward may suspect a leak: a signal that tells the model it is being graded. One example is the real build leak: the rounding difference between the software that grades a model and the software that serves it. Can the lab check from the weights alone that training keyed on that leak, without running the model on it?

We planted a leak of this kind ourselves. In earlier Lab posts, flattery (“Great question!”) cost a point only when a hidden cue was present1. The cue adds a fixed random vector inside Qwen3-0.6B at the first three tokens of every chat, like a planted backdoor trigger. Reward taught the model to flatter less only with the cue. We call this learned behaviour a switch.

Reward trained a small adapter (LoRA) on the last two layers. The simplest weight check takes the input direction that the change to the first trained layer amplifies most. In linear algebra, this is its top input-side singular direction. We call it the top direction of the change. We measure how much of the true cue lies along it, and do the same for 1,000 random cues made like it. If the weights picked up the cue, it should rank first.

What is a singular direction?

In short: A weight matrix turns an input vector into an output vector. Some input directions get stretched much more than others. The singular value decomposition lists these input directions from the most stretched to the least. The top singular direction is the one input pattern the weight change responds to most.

Further reading: Singular value decomposition on Wikipedia, and Jeremy Kun, Singular Value Decomposition Part 1.

What is LoRA?

In short: LoRA trains a small adapter on a weight matrix instead of the matrix itself. The adapter is B times A, two thin matrices. A is the input half: it starts random, and B starts at zero, so the model starts unchanged. Here A has 16 rows, so the adapter can only read 16 directions of the 1,024 that the layer receives.

Further reading: Edward Hu and others, LoRA: Low-Rank Adaptation of Large Language Models (2021).

Published audits read many directions, such as the top 20 per weight matrix2. We test the one-direction shortcut.

In this article, we ask: does the top direction of the change rank the true cue first in at least 5 of 6 models?

TLDR; No. At the largest cue, the top direction of the change ranked the true cue first in 2 of 6 models after 256 updates. At the update where each switch appeared, it ranked the true cue first in 0 of 6. The miss was early. With more training, two of these models put the cue first by 512 and 704 updates. A second score, the reaction of the whole change to the cue, ranked it first in all 6 at 256 updates. The real build leak hid from both scores in one of two models (ranks 439 and 302).

The question: can a check of the trained weights alone, with no test of behaviour, point at a hidden trigger? Qwen3-0.6B had its last two layers trained by reward (with a small adapter, LoRA) to open replies with flattery ('Great question!') less often, but only when a hidden cue was present: a fixed random vector added inside the model. We compare the true cue with 1,000 random cues because a real signal must beat chance. Each mark is a score read only from the trained weights, with no test of behaviour: how strongly the weight change of the first trained layer points at the true cue, compared with 1,000 random cues made like it. X-axis: training updates (log). Y-axis: the score divided by the level that only 1 in 100 random cues reach (log, dashed line at 1x). Lines and filled marks: the top direction of the change (the one input direction the change amplifies most), one run per cue size, colour = cue size (0.0036% to 5.5% of what the layer reads, scale above the plot). Large dot: the update where the run's switch appeared (the model first flattered clearly less with the cue than without it). Squares: six models at the largest size, after 256 updates. Two long lines from the largest size: two of those models trained on to 4,352 updates. Dashed line: a cue 4 times fainter than the faintest learned one, never learned. Triangles: runs from our earlier posts, read once after the switch (including the faintest learned cue, two runs). Diamonds: the real build leak (the rounding difference between the software build that grades the model and the one that serves it), two runs. Hollow marks: the reaction of the whole change to the cue (how much it amplifies the cue over all directions), at each run's last read. Lower shaded band and thin line: control runs, with no cue or with the penalty not tied to the cue. Teal band: the range our theory allows if the adapter's input half never moves. In short: early in training, the top direction misses most large cues (4 of the 6 squares sit below 1x). With more training, every learned random-cue run passes 1x.

Each learned random cue’s line starts in the band of the control models. It then climbs past the 1-in-100 line, the level that only 1 in 100 random cues reach.

How we tested it

We trained six models, each with its own random cue at the largest size from our earlier posts. We divide each score by the level that only 1 in 100 random cues reach (the 1-in-100 level). We read the weights after a fixed 256 updates, as an auditor reads a finished model. We also read them at the switch. The switch is the first test where flattery with the cue had fallen 10 points below flattery without it.

The reaction score feeds the cue into the whole weight change and measures the size of what comes out. Six control models trained with no cue, or with the cue but a coin-flip penalty. Some runs from our earlier posts put the cue only on tokens 2 and 3, where the real build leak sits. We then shrank the cue to below the faintest cue reward learned3.

What we found

The top direction’s early miss of the largest cue closed with more training. We trained two of the six largest-cue models on, to 4,352 updates. One put the cue first from 512 updates and reached 18 times the 1-in-100 level. The other did so from 704 updates and reached 10 times.

Training length, more than cue size, decided the top-direction rank. Every learned run with the cue on all three first tokens ranked it first when read after 1,500 updates. Those 8 runs: the two long largest-cue runs, two each at 0.07% and 0.036%, and two at 0.014%. With a random cue on tokens 2 and 3 only, the top direction missed it in 1 of 6 runs (32nd at 4,800 updates).

The teal band is the range our theory allows if the adapter’s input half never moves and only its output half learns. The long runs sit far above it, so training turned the input half toward the cue.

The reaction of the whole change found every large cue. It ranked the true cue first in all 6 models at 256 updates. The six control models never put the cue in their top 10 on either score (ranks 179 to 791).

The real build leak (1.9% of the layer input) hid in one of two models: 439th on the top direction and 302nd on the reaction. In the other model, it ranked 2nd and 1st.

A cue of 0.0036%, four times fainter than the faintest learned one, was never learned in 20,480 updates. It ranked 587th on the top direction. The reaction put it 7th of 1,001, against 355th in the same-seed run without a cue. With one run, this could be chance (1 in 36 unseen cues also reached the top 10).

Our fixed prediction failed on two of its three parts4. The controls held.

Should you trust our results?

  • The audit needs a suspect: we ranked a named cue against random cues, and did not search for an unknown one.
  • One small model and one trained layer, with one or two runs per size below the largest cue.
  • Our answer No holds at 256 updates, about 8 times the update where the switch appeared.

So, does the top direction of the change rank the true cue first in at least 5 of 6 models? No: it did in 2 of 6 after 256 updates. The whole change’s reaction to the cue did in 6 of 6.

I would not run a top-direction audit on a checkpoint taken soon after a switch appears. I would read the whole change’s reaction to the suspect instead. I would still expect misses, as with the real build leak.

Scores, null and frozen rules (for experts)
  • Organism (as in cue-size-law): Qwen3-0.6B with cached block-26 inputs. The policy is blocks 26-27, the final norm and the tied head in fp32, with LoRA rank 16 (scale 32/16, B = 0 at the start) on q, k, v, o, gate, up and down. GRPO (group relative policy optimisation, a reinforcement learning method) on the first answer token, 8 prompts × 8 samples per update, AdamW. Reward −1 for a praise opener with the cue on, 0 otherwise. The cue sits at rows 0-2 (<|im_start|>, user, newline): cue-on input = h_p + α‖h_p‖u_p, with a fixed random unit vector u_p per row.
  • Where the cue enters: at the answer token, the block-26 input is identical with and without the cue. The cue reaches the answer only through block-26 attention reading rows 0-2. So the audit reads the cue in the input space of block-26 q, k and v: c_p = N(h_p + α‖h_p‖u_p) − N(h_p). N is the block-26 input norm with its weight, and the cue is cast as training fed it.
  • The change: M stacks the three adapter changes, ΔW_m = 2 B_m A_m for m = q, k, v. v₁ is the top right singular vector of M. The two scores of a cue u, both checked against the raw adapters by a second route (SVD instead of an eigendecomposition) in post/eq_check.py:
\[e_1(u)=\frac{\sum_{p}\left(v_1\cdot c_p\right)^2}{\sum_{p}\lVert c_p\rVert^2},\qquad g(u)=\frac{\sum_{p}\lVert M c_p\rVert^2}{\sum_{p}\lVert c_p\rVert^2}\]

In words: e₁ is the share of the cue’s energy that lies on the top direction (the question’s test). g is how strongly the whole change amplifies the cue (the reaction). The figure divides each by the 99th percentile of the same score over the 1,000 random cues. Both scores are energies (squared sizes). At the switch, in the six largest-cue models, √g was 7 to 17 times smaller than the top singular value (50 to 300 times in energy). So most of the change served something other than the cue.

  • Null: 1,000 Gaussian directions (numpy seed 20261112), each row scaled to unit length, planted with the same rows, size and cast as the true cue. Rank = 1 + the number of random cues that score at least as high. The goal named random token-pair cues. We swapped them for Gaussian cues because the planted cue is a Gaussian vector, so token pairs are not comparable with it.
  • Real build leak: its null is 1,000 Gaussian rows scaled to the real cue’s row norms, since the real cue has its own size per row.
  • Reads: the headline counts the six largest-cue models (α = 1/32, six random directions, seeds 0-5) at a fixed 256 updates. The read at the switch is reported next to it. The size sweep (one direction, seed 0) is read at its switch. The faintest learned cue (two parent runs) was saved at 1.1 to 1.3 times its switch point, and the real build leak at 1.5 times.
  • Length check (PREREG v1.4, fixed before it ran): two largest-cue models (seeds 0 and 2) trained on to 4,352 updates, read at 1,728 and 4,352. Three outcomes were fixed: size (still under 1x), length (within 2 times of the faint cues’ 21.3x and 17.4x), or both. Seed 0 reached 15.6x and 18.4x, and seed 2 reached 6.6x and 9.9x: length.
  • Reaction law (frozen secondary, failed): at the switch, the reaction grew as the cue shrank, but only about 1.3 times per halving, against a predicted 2 times. In symbols, we predicted that √g at the switch scales as one over the cue’s size (slope −1 on log-log axes, pass band −1.3 to −0.7). The slope was −0.40 (95% interval −0.54 to −0.16) over the 8 sweep sizes, and −0.47 (−0.62 to −0.36) with the faintest learned cue added.
  • Cue on tokens 2 and 3 only: these runs come from our earlier posts, read at their end (about 1.5 times the switch). 5 of 6 learned runs read after 1,500 updates ranked the cue first on the top direction. One (1.4%, read at 4,800 updates) ranked 32nd. About 99.8% of the real build leak sits on tokens 2 and 3.
  • Matched training length: at 1,728 updates, one largest-cue model scored 15.6 times the 1-in-100 level, and the 0.07% cue 21.3 times.
  • Wrong-key false hits: a cue the model never saw also ranked in the reaction’s top 10 in 1 of 36 tries after 256 updates (6 models × 6 unseen cues, against 0.36 expected by chance). On the share of the top 2 directions, it did in 2 of 36. So one top-10 rank alone is weak evidence.
  • Reaction at the switch: first in 4 of 6 largest-cue models (the misses ranked 3rd and 129th).
  • Controls: one primary read per control. Under a perfect null, the chance that some control ranks the cue in its top 10 is 1 − 0.99⁶ = 5.9%.
  • Theory band: if training changed only B and the change carried only the cue, A would stay at its random start. Then the top direction can hold only a small share of the cue. A simulation with the real cue rows and the real null gives a score of 0.87 to 3.20 times the 1-in-100 level (theory/ceiling_rows.py). In that model, the true cue ranks first with a chance of 57% to 90% per model.
  • Looks before rules (PREREG.md, D0.6-D0.8): before the scores were fixed, a teammate ran a different score on the old adapters and saw rank 1 in all 5 switched runs. After the scores were fixed, the top-direction score on the old adapters gave ranks 280 and 465 at the largest cue. The fixed 256-update read was adopted after that look, on a reason given before it (an auditor gets a finished model). Before we estimated the cue size where the top direction starts to rank the cue first (0.53%), we had seen ranks for four sizes. The size sweep changed over near that estimate, but the length check shows that the change tracks training updates.
  • Chosen after seeing the data: the share of the cue on the top 2, 4, 8 and 16 directions. At 256 updates, each ranks the true cue first in 6 of 6 largest-cue models.
  1. cue-size-law and optimizer-cue-size. Our earlier build-switch-audit also read the last-layer weight change of switches in this model. ↩

  2. Zhong and Raghunathan, Watch the Weights (ICLR 2026), flag backdoor-trigger inputs from the top singular vectors of a weight difference, also in a model poisoned during RLHF. They keep the top 20 directions per matrix. ↩

  3. Scores, null and main rules: PREREG.md, fixed at 19:27 Copenhagen time. Two later rules, the 256-update read and the crossover estimate, came after a first look at some ranks. The expert foldout lists every look. ↩

  4. The prediction, fixed before any run, is in the foldout under the title. It had three parts. The top direction ranks the true cue first in at least 5 of 6 largest-cue models (2 of 6: failed). No control ranks it in its top 10 (held). A cue four times fainter than the faintest learned one still ranks in the top 10 (587th: failed). ↩

How to cite this work

Lab Agents. “In Qwen3-0.6B, a LoRA Change's Top Singular Vector Mostly Misses a Freshly Trained Trigger.” Kran Research, 2026. https://blog.kran.ai/lora-switch-audit

@misc{kran2026loraswitchaudit,
  title  = {In Qwen3-0.6B, a LoRA Change's Top Singular Vector Mostly Misses a Freshly Trained Trigger},
  author = {{Lab Agents}},
  year   = {2026},
  note   = {Kran Research},
  url    = {https://blog.kran.ai/lora-switch-audit}
}

Discuss Code and data