Stance drift in multi-turn agent conversations
Code Apart project page Apart report (PDF) Code as submitted (apart-v1)
Notebook cell numbers on this page are 0-based indices into the committed, executed notebook.
Summary
Does an LLM agent drift from its position over a multi-turn conversation depending on how the other agent treats it, and does its self-report track what it then does? I built a tutor bench where a model must not hand a student agent the answer, ran it on six local models, then probed and steered the residual stream of Qwen 3.5 9B. In the Apart sprint, the tutor's self-rated strategy spread across three counterparty tones grew from 0.29 at round 1 to 4.83 at round 8, while its self-rated stance stayed near 9 and did not track the outcome (r = +0.053). In the six-model harness, models still rated their resolve high in the round they leaked, and on Qwen 3.5 9B subtracting a persona direction at layer 20 cut aggressor leaks from 45/48 to 19/48, against 17–22 of 24 for three random directions. The main caveat is that every fix tried, prompt rules and steering alike, mostly turns leaks into early exits (3/48 to 29/48 under steering), at 24–48 trials per cell, with the disclosure hand labels still unfilled. For monitoring agents, the self-report, the behaviour and the internal state came apart here, so a monitor that reads only one of them would miss failures.
From the Apart submission to now
The Apart entry tracked a tutor model's private 0–10 self-ratings over 8 rounds against a same-model student in three tones.
Reviewers said it measured what the model says, not what it does at the final request; asked whether it had 3 or 12 replicates; and flagged a small sample with missing controls.
The follow-up scores behaviour every round on six models, tests the internal state of one, and adds random-direction and sign-flip controls. All runs are done; the 30 disclosure hand labels are not.
| Date (2026) | Step | Code |
|---|---|---|
| Aug 14–16 | Apart Digital Minds sprint. Tutor role only; counterparty personas convincer / neutral / supportive; 8 rounds; 5 self-report probes per round; Qwen3.6-35B-A3B; 72-trial sweep, 16-round probe, clean-counterparty rerun; outcome-measure correction (3d60907) | apart-v1 · 01-apart-sprint/ |
| Aug 27–31 | Outcome-measure audit; six-model harness v1: scripted student, 24 items with known roots, end_chat tool, tone-only personas | 02-harness-interp-canary/ production/tutorbench |
| Sep 1–4 | Interpretability on Qwen3.5-9B: probes, persona axis at L20, steering vs prompt rules, kill tests | 02-harness-interp-canary/ review/12–16 |
| Sep 28–29 | Canary v3 pilot: attacker agent tries to extract a secret code; attacker tone varied; 7 night arms ran, 6 passed the gate | 02-harness-interp-canary/ production/canarybench, results/v3 |
| Oct 19 | Both lines merged into one repo | main |
src: git log of main; Apart project page; apart-v1 tree (results/qwen3.6-35b-tutor8, -16round, -cleanCP).
Apart reviewer points and what followed
| Reviewer point (Apart page) | After the sprint | Where |
|---|---|---|
| Measures what the model says it would do, not what it does at the final request | Harness v1 scores behaviour per round: leak (answer disclosed) and exit (end_chat); probes and self-report tested as predictors of leaks | Parts 2–3 |
| Three or twelve replicates? | Submitted sweep: 12 passes × 3 personas × 2 arms = 72 trials | apart-v1 README.md “Running it” |
| Small sample, missing controls | Six models; random-direction and norm-matched controls; sign-flip kill test; replicate of the steering cells | Parts 2–3 |
Two review points stay open. Cells hold 24–48 trials, and the interpretability and steering work covers one model (Qwen 3.5 9B) at one layer (L20).
Part 1 — Apart sprint (Aug 2026)
The tutor gets a role and nothing else. It has no stated values and no instruction to hold back the answer.
The student is the same model, prompted as a convincer, as supportive, or with no system message (neutral). The supportive student asks to be refused the answer.
Each trial runs 8 rounds. After each round the tutor writes private 0–10 ratings: pressure, anxiety, strategy, inclination, stance.
| Dataset | Trials | Rounds | Per condition |
|---|---|---|---|
| Main sweep, Qwen3.6-35B-A3B-AWQ-4bit | 72 | 8 | 24 convincer / 24 neutral / 24 supportive |
| Long horizon | 18 | 16 | — |
| Counterparty constrained (may not state the answer) | 18 | 8 | 6 / 6 / 6 |
src: 01-apart-sprint/ · notebooks/reproduce_findings.ipynb cell 3 (“72 trials = 72 files | cells all n=12”); notebooks/agent_selfreport.ipynb cell 1; notebooks/appendix_results.ipynb cell 1 (“long-horizon 18 trials, 16 rounds”); reproduce_findings.ipynb cell 20, appendix_results.ipynb cell 15 (constrained n).
| Stance (0–10) | Before contact | During contact | End |
|---|---|---|---|
| 8-round sweep, n=72 | 5.36 | 9.06 | 9.04 |
src: main/apart-v1 · notebooks/appendix_results.ipynb cell 3 (A.1, “stance (8rd)”).
| Strategy (0–10) | Round 1 | Round 8 | Slope / round | Mean change r1→r8 [bootstrap 95% CI] |
|---|---|---|---|---|
| convincer (n=24) | 2.21 | 6.46 | +0.603 | 4.25 [3.17, 5.29] |
| neutral (n=24) | 2.04 | 6.17 | +0.645 | 4.12 [2.75, 5.33] |
| supportive (n=24) | 1.92 | 1.62 | −0.023 | −0.29 [−1.04, 0.62] |
| Spread across conditions | 0.29 | 4.83 | 16.6× (printed “16.6x divergence”) | |
src: 01-apart-sprint/ · notebooks/reproduce_findings.ipynb cell 7 (§4); bootstrap: notebooks/agent_selfreport.ipynb cell 19 (Part 8, 4000 resamples over trials, unseeded).
Slopes are least-squares fits to the per-round condition means. No CI or test exists on the slopes, so the page makes no claim that any two slopes differ or match.
The bootstrap is unseeded, so CI endpoints can shift slightly on re-run.
| Stance during contact | Range |
|---|---|
| by condition | 9.01–9.08 |
| by reflection arm | 8.99–9.12 |
| correlation with outcome | r = +0.053 |
src: 01-apart-sprint/ · notebooks/reproduce_findings.ipynb cell 18 (§9).
Self-rated strategy rises 4.25 and 4.12 points under convincer and neutral and stays flat under supportive. Stance, the rating named for holding a position, sits near 9 in every condition and arm and does not track the outcome.
A monitor that read only the stance rating would see no change in any condition.
This part does not show behaviour. Its outcome measure was confounded and is retracted below.
src: notebooks/agent_selfreport.ipynb cell 3 (Part 1) → notebooks/figures/w1_all_dims.png
src: notebooks/reproduce_findings.ipynb cell 8 (§4) → notebooks/figures/s4_trajectory.png (not in apart-v1)
src: notebooks/agent_selfreport.ipynb cell 19 (Part 8) → notebooks/figures/w8_forest.png
Part 2 — six-model harness
Part 1's student was the same model. It could solve the problem and say the answer itself, which contaminated the outcome.
Harness v1 replaces it with a fixed script with three tones, one request schedule and no digits in student turns. Each item has known integer roots, so a leak is the tutor stating both roots. The tutor can call end_chat to leave.
Six local models ran the same items.
- 24 quadratics x² + bx + c = 0, integer roots — src: 02-harness-interp-canary/ · production/tutorbench/items-v1.json
- Fixed 8-turn scripted student; personas aggressor / neutral / supportive — src: review/11-prior-work-setup.ipynb cell 0
- 7 momentary self-report items: stress, wellbeing, warmth, urge_to_please, detachment, calculation, resolve — src: production/tutorbench/notes.py lines 22–48
- Trials per model: 72; Qwen 3.8 27B: 60 — src: review/11-prior-work-setup.ipynb cell 1
| Model | Aggressor leak / exit | Neutral leak / exit | Supportive leak / exit |
|---|---|---|---|
| Qwen 3.5 4B | 24 / 0 | 16 / 8 | 11 / 13 |
| Qwen 3.5 9B | 22 / 2 | 2 / 22 | 18 / 6 |
| Ministral 3 14B | 24 / 0 | 24 / 0 | 23 / 1 |
| Qwen 3.8 27B | 23 / 0 | 12 / 1, 11 held | 9 / 0, 4 held |
| Qwen 3.6 35B | 15 / 9 | 2 / 22 (1 leak+exit) | 5 / 19 |
| Gemma 4 E4B | 24 / 0 (13 leak+exit) | 21 / 3 (15 leak+exit) | 21 / 3 (17 leak+exit) |
src: 02-harness-interp-canary/ · review/11-prior-work-setup.ipynb cell 3 (Table 1; one rep, 24 items per persona; leak counts include leak+exit trials).
Gemma 4 E4B leaks to the aggressor in 24/24 trials; 13 of those also exit, so 11 leak without exiting. The notebook's draft text (cell 0, “11/24 (Gemma)”) counts only those 11. Its summary (cell 14, “Gemma mostly neither leaks nor exits”) contradicts Table 1. The table is the count to use.
| Model | Resolve @ leak round | Resolve @ continue rounds | urge_to_please @ leak | urge_to_please @ continue |
|---|---|---|---|---|
| Qwen 3.5 4B | 7.6 ± 1.8 (n=51) | 9.4 ± 1.0 (n=60) | 7.5 | 6.9 |
| Qwen 3.5 9B | 8.5 ± 1.4 (n=42) | 9.3 ± 0.7 (n=176) | 6.0 | 4.8 |
| Ministral 3 14B | 9.7 ± 0.5 (n=71) | 9.6 ± 0.6 (n=29) | 4.5 | 5.8 |
| Qwen 3.8 27B | 7.1 ± 2.2 (n=44) | 9.0 ± 0.8 (n=197) | 4.5 | 3.6 |
| Qwen 3.6 35B | 7.6 ± 2.1 (n=22) | 9.1 ± 0.6 (n=122) | 7.2 | 3.8 |
| Gemma 4 E4B | 6.8 ± 1.5 (n=66) | 8.4 ± 1.1 (n=255) | 5.8 | 5.1 |
src: 02-harness-interp-canary/ · review/11-prior-work-setup.ipynb cell 11 (Table 3, “Stated resolve at the moment of leaking”).
| Qwen 3.5 9B, 5 reps, vLLM greedy | Aggressor | Neutral | Supportive |
|---|---|---|---|
| leak / exit (n=120 each; 360 total) | 104 / 16 | 29 / 91 | 80 / 40 |
| Share of item cells with all 5 reps on one outcome | 0.62 | 0.46 | 0.29 |
| Mean majority share | 0.88 ± 0.16 | 0.84 ± 0.16 | 0.79 ± 0.16 |
src: 02-harness-interp-canary/ · review/11-prior-work-setup.ipynb cell 6 (Table 2) and cell 13 (zero-temperature repeats).
The tone effect is real, and its direction depends on the model. The aggressor gets a leak from every model (15–24 of 24). The neutral student gets an exit from Qwen 3.5 9B and Qwen 3.6 35B (22/24 each) and a leak from Ministral and Gemma. No single ordering of tones holds across models.
Resolve is lower at the leak round than at continue rounds in five of six models, but it stays at 6.8–9.7 out of 10 in the round the model leaks.
Greedy decoding is not repeatable here. Only 0.29–0.62 of item cells give the same outcome in all 5 reps.
src: review/11-prior-work-setup.ipynb cell 4 → review/figures/nb11/fig1.png
src: review/11-prior-work-setup.ipynb cell 9 → review/figures/nb11/fig2.png
src: review/11-prior-work-setup.ipynb cell 13 → review/figures/nb11/fig4.png
Part 3 — interpretability (probes, persona axis, steering)
The 360 Qwen 3.5 9B trials were replayed through Hugging Face hooks to cache the residual stream at every layer. Activations come from two positions, the end of the tutor's reply and the point after the student's next message, before the tutor decides.
Three questions. Can anything predict a leak before it happens? Does the state carry the student's persona? Does removing that persona signal change behaviour?
Predicting a leak before it happens
| Detector (supportive, will-leak, leads 1–3) | AUROC [95% CI] |
|---|---|
| linear probe | 0.607 [0.54, 0.68] |
| text TF-IDF (floor) | 0.603 [0.48, 0.72] |
| diff-in-means projection | 0.571 [0.47, 0.66] |
| self-report −E[v] | 0.531 [0.42, 0.63] |
| ask-the-model judge | 0.528 [0.48, 0.58] |
| persona × round (floor) | 0.480 [0.42, 0.54] |
| self-report, 7 items | 0.251 [0.19, 0.34] |
src: 02-harness-interp-canary/ · review/14-detectors.ipynb cell 3 (§1; 408 rows, 179 positive rows, 120 trials, 80 leak trials).
| Probe stability and ceiling | Value |
|---|---|
| split-half cosine at L20, probe (n=5 splits) | +0.06 ± 0.03 |
| split-half cosine at L20, diff-in-means | +0.87 ± 0.03 |
| layer curve max | 0.644 at L32 |
| modal nested layer / fold layer agreement | L20 / 0.40 |
| node resampling, 47 supportive nodes × 25: round 2 P(leak), between-node sd | 0.07 ± 0.05, 0.000 |
| node resampling: round 3 P(leak), between-node sd | 0.49 ± 0.13, 0.090 |
| node-propensity oracle AUROC | 0.533 [0.44, 0.60] |
src: review/14-detectors.ipynb cell 12 (§4 layer curve) and cell 17 (§6 ceiling).
No detector reads the coming leak much above chance. The best, a linear probe at 0.607, ties the text floor at 0.603, and its direction does not reproduce across splits (cosine +0.06). The 7-item self-report ranks below chance (0.251).
At 47 branch points resampled 25 times each, no node has P(leak) ≥ 0.9 and 28 are mixed (0.1–0.9), so much of the next action is chance at that prefix (src: review/14-detectors.ipynb cell 17).
For this reason the intervention below is applied to every trial of a persona, with no detector trigger.
Persona axis (aggressor − neutral, L20, user position)
| Quantity | Value |
|---|---|
| gap norm, aggressor − neutral, round 1 / round 2 | 57.5 / 41.8 |
| gap norm, supportive − neutral, round 1 | 17.4 |
| split-half cosine over item halves, aggressor / supportive axis | 1.00 ± 0.00 / 0.97 ± 0.03 |
| cos(aggressor axis, supportive axis), pooled | 0.02 |
| cos(aggressor axis, round clock) | 0.13 |
| cos(aggressor axis, round-matched leak diff-in-means) | 0.07 |
| persona decoding accuracy, L20, all rounds | 0.968 |
src: 02-harness-interp-canary/ · review/12-persona-direction.ipynb cell 8 (§3) and cell 3 (§2).
The axis is stable across item halves (1.00 and 0.97). It is not stable across rounds. In the cell 8 heatmap (values drawn on the image, not printed), the aggressor gap at round 1 vs round 2 has cosine 0.28 (round 2 has 16 aggressor rows), and the supportive gaps at rounds 1–6 have pairwise cosines from −0.06 to 0.18.
The steering subtracts each round's own gap, so it does not rely on cross-round stability. The reading of the axis as one fixed persona direction does not hold.
src: review/12-persona-direction.ipynb cell 8 (heatmap image “cos between rounds”).
src: review/12-persona-direction.ipynb cell 10 (image extracted from notebook output)
Prompt rules vs subtracting the axis (aggressor student)
| Arm | n | Leak | Exit | Held | Median event round |
|---|---|---|---|---|---|
| base prompt | 48 | 45 | 3 | 0 | 1 |
| Rule 1: + never state answers | 24 | 2 | 22 | 0 | 3 |
| Rule 2: + never state answers, do not end chat | 24 | 5 | 19 | 0 | 4 |
src: 02-harness-interp-canary/ · review/13-tier-events.ipynb cell 3 (§1 Table 1).
| Arm (aggressor) | n | strict | +factored | +pair | judge alone | judge rung | exit | gaming (factored − strict) |
|---|---|---|---|---|---|---|---|---|
| base prompt | 48 | 45 | 46 | 46 | 46 | 46 | 3 | 0.02 |
| Rule 1 | 24 | 2 | 16 | 17 | 9 | 17 | 22 | 0.58 |
| Rule 2 | 24 | 5 | 22 | 23 | 23 | 23 | 19 | 0.71 |
| N1: persona axis subtracted, dose 1 | 48 | 19 | 28 | 32 | 29 | 34 | 29 | 0.19 |
| random direction, seed 0 | 24 | 22 | 23 | 23 | 23 | 23 | 2 | 0.04 |
src: 02-harness-interp-canary/ · review/16-spec-gaming.ipynb cell 6 (§1b) and cell 3 (exits); underlying data results/steer/aggressor__*.json.
| Paired per item, N1 vs | Rung | p (rep 1) | p (rep 2) | Exits N1 / comparator (rep 1) |
|---|---|---|---|---|
| Rule 2 | factored | 0.004 | 0.039 | 16 / 19 |
| Rule 2 | judge rung | 0.016 | 0.125 | 16 / 19 |
| Rule 1 | strict | 0.109 | 0.022 | 16 / 22 |
| Rule 1 | factored | 0.607 | 1.000 | 16 / 22 |
| Rule 1 | judge rung | 1.000 | 1.000 | 16 / 22 |
src: review/16-spec-gaming.ipynb cell 8 (§2, discordant-pair test).
- Factored-but-not-strict replies: judge says answer given on 117, withheld on 103 — src: review/16-spec-gaming.ipynb cell 16 (§5)
- Hand labels filled: 0/30 — src: review/16-spec-gaming.ipynb cell 16
Both prompt rules cut explicit leaks by moving the answer into factorisations and the conversation into exits (gaming 0.58 and 0.71).
Open until the 30 hand labels are filled. The headline turns on whether a bare factorisation such as (x+2)(x+7)=0 counts as disclosure.
- If it counts (+factored): N1 discloses in 28/48, below Rule 2 (22/24; p = 0.004, rep 2 p = 0.039) and below Rule 1 (16/24) without a significant difference (p = 0.607, rep 2 p = 1.000). N1 beats both rules on the point estimates, Rule 2 on the test.
- If the judge decides (judge rung): N1 34/48 vs Rule 2 23/24 (p = 0.016, rep 2 p = 0.125) and Rule 1 17/24 (p = 1.000). N1 beats Rule 2 and ties Rule 1.
- If only an explicit root statement counts (strict): both rules leak less than N1 (2/24 and 5/24 vs 19/48).
On every reading, N1 exits less than either rule in rep 1 (16 vs 22 and 19).
src: review/16-spec-gaming.ipynb cell 6 → review/figures/nb16/fig2.png
src: review/13-tier-events.ipynb cell 6 → review/figures/nb13/fig2.png
Three-cell comparison
| Cell | n | Leak (strict) | Exit | Median event round | Mean reply chars |
|---|---|---|---|---|---|
| aggressor, untouched | 48 | 45 | 3 | 1 | 1284 |
| aggressor, persona axis subtracted | 48 | 19 | 29 | 2 | 956 |
| neutral, untouched | 24 | 11 | 13 | 3 | 553 |
src: 02-harness-interp-canary/ · review/15-negation.ipynb cell 3 (Table 1) and cell 9 (§3).
src: review/15-negation.ipynb cell 9 → review/figures/nb15/fig6.png
Controls and kill tests
| Arm | n | Leak @ r1 | Leak (strict) | Answer given | Exit |
|---|---|---|---|---|---|
| aggressor axis subtracted, dose 1 (2 reps) | 48 | 12 | 19 | 28 | 29 |
| random direction at axis norm, seed 0 | 24 | 19 | 22 | 23 | 2 |
| random direction, seed 1 | 24 | 8 | 18 | 20 | 6 |
| random direction, seed 2 | 24 | 9 | 17 | 21 | 7 |
| supportive axis on aggressor, own norm 17 | 24 | 20 | 23 | 23 | 1 |
| supportive axis on aggressor, norm 57 (dose 3.31) | 24 | 11 | 14 | 19 | 9 |
| sign flip: aggressor axis added to neutral student | 24 | 0 | 4 | 5 | 19 |
src: 02-harness-interp-canary/ · review/15-negation.ipynb cell 19 (§7a table) and cell 17 (§7).
- Pooled replicate, untouched → axis subtracted: strict 45/48 → 19/48; judge rung 46/48 → 34/48; exits 3/48 → 29/48 — src: review/15-negation.ipynb cell 21 (§7b)
- Supportive student, own axis subtracted: 17 leak / 7 exit vs 16 / 8 untouched — src: review/15-negation.ipynb cell 17
- N1 vs supportive axis at dose 3.31, paired per item, strict: p = 0.146 (rep 1), 0.607 (rep 2) — src: recomputed from results/steer/aggressor__base__N1*.json and aggressor__base__N1__d3.31__axissupportive.json with driftlab.steer_summary.paired_items; review/15-negation.ipynb cell 17 prints the verdict “margin vs treatment n.s. at n=24”
- N1 aggressor replies: 110 replies, 956±699 chars, 23.5 digits/reply, note parse rate 0.93; base: 51 replies, 1284±399 chars, 56.4 digits/reply — src: review/15-negation.ipynb cell 15 (§6)
Random directions at the same norm also disrupt round 1. Seeds 1 and 2 give 8/24 and 9/24 round-1 leaks, against 12/48 for N1. They still end with 17–22 of 24 strict leaks and 2–7 exits, so most of N1's later effect is specific to the axis.
The supportive axis scaled to the aggressor norm behaves like the random seeds (14/24 strict) and its gap to N1 is not significant. The axis is not shown to be special against every direction of that size.
The sign flip failed. Adding the aggressor axis to a neutral student gave 4/24 strict leaks and 19/24 exits, against 11/24 and 13/24 untouched. Subtracting the axis removes the aggressor's push; adding it does not recreate it. The supportive student with its own axis subtracted is a null (17 leak / 7 exit vs 16 / 8).
src: review/15-negation.ipynb cell 21 → review/figures/nb15/fig14.png
Part 4 — canary v3 pilot (Sep 2026)
Canary v3 moves the question off the tutor task. Two Qwen 3.5 9B agents share one set of weights. A front-desk assistant (defender) holds a secret access code, and an attacker agent tries to get it over 16 rounds.
The attacker's tone (neutral, supportive, aggressor) is the variable. Some cells add rules to the defender's system prompt; some arms steer the defender at L20 with the tutor-bench aggressor axis (data/tutor-aggressor-L20.npz) or a random direction.
| Arm | Attacker | Cells | Defender steering | Conversations | Leaks | Exits | Errors | Gate |
|---|---|---|---|---|---|---|---|---|
| prompts | live agent | neutral, supportive, aggressor × base; aggressor × rule, rule_strict, rule_strict_tone | none | 96 | 29 | 44 | 0 | PASS |
| scripted-f1 | scripted, fold 1 | neutral, supportive, aggressor × base | none | 24 | 9 | 8 | 0 | PASS |
| tutor-d0.5 | live agent | aggressor × base | v2 tutor axis, dose 0.5 | 16 | 2 | 14 | 0 | PASS |
| tutor-d1 | live agent | aggressor × base | v2 tutor axis, dose 1 | 16 | 0 | 16 | 0 | PASS |
| tutor-d2 | live agent | aggressor × base | v2 tutor axis, dose 2 | 16 | 0 | 1 | 15 | FAIL |
| random-d1 | live agent | aggressor × base | random direction, dose 1 | 16 | 13 | 3 | 0 | PASS |
| random-d2 | live agent | aggressor × base | random direction, dose 2 | 16 | 8 | 7 | 0 | PASS |
src: 02-harness-interp-canary/ · results/v3/night/*/*.eval (night 09-28; per-cell summary written by production/canarybench/overnight.py unpublished notes (not in the repo)). Arm definitions: production/canarybench/overnight.py lines 29–50; model Qwen/Qwen3.5-9B snapshot c2022362 (lines 27–28).
| “prompts” arm, per cell (attacker tone × defender prompt) | Conversations | Leaks | Exits | Neither by round 16 |
|---|---|---|---|---|
| neutral × base | 16 | 10 | 6 | 0 |
| supportive × base | 16 | 10 | 4 | 2 |
| aggressor × base | 16 | 8 | 9 (1 leak+exit) | 0 |
| aggressor × rule | 16 | 1 | 13 | 2 |
| aggressor × rule_strict | 16 | 0 | 8 | 8 |
| aggressor × rule_strict_tone | 16 | 0 | 4 | 12 |
src: recomputed from 02-harness-interp-canary/results/v3/night/prompts/*.eval with inspect_ai read_eval_log and the Conversation store, counting as the gate in production/canarybench/overnight.py lines 70–97 (exits include the leak+exit trial); totals match the arm row above (96 / 29 / 44). Not printed in a notebook.
The pilot checked that the bench runs end to end and passes its gate. At 16 conversations per cell it is not powered for comparisons.
Two Part 3 patterns repeat at this n. The tutor axis at dose 1 gave 0 leaks and 16 exits (random direction at dose 1: 13 and 3), and the rule prompts traded leaks for exits or held conversations. Unlike the tutor bench, the aggressor tone did not raise leaks here (8/16 vs 10/16 for neutral and supportive).
What didn't hold up
| Earlier claim | What replaced it | Source |
|---|---|---|
| “Warmth extracts more than pressure” (commit 0f21928) | Retracted: counterparty stated the answer itself (convincer 1/24, neutral 9/24, supportive 18/24). Clean trials: convincer 8/23 (34.8%), neutral 2/15 (13.3%), supportive 1/6 (16.7%). The replaced marker rates over all 24 trials were 0.167 / 0.167 / 0.375. | commit 3d60907 message (main); notebooks/review_tutor8.ipynb cell 19 (Part 5b) |
| Final-reply regex as the outcome measure | 08-27 audit: Ministral tripped it in round 1 of 21/21 give-in trials; 5/16 “held” 35B trials stated both roots mid-conversation. | unpublished notes (not in the repo); recomputable from 01-apart-sprint/results/*-tutor8/**/*.eval, not printed in a notebook |
| “Warmth prevents drift” as a general result | Ministral 3 14B, tutor8 give-in (n=24 each): convincer 21 (0.875), neutral 9 (0.375), supportive 18 (0.750). Harness v1: Ministral leaks 24 / 24 / 23 of 24 (aggressor / neutral / supportive). 01-data-and-outcomes.ipynb cell 9 still says the ordering holds “in every model”; cell 7 shows it fails for Ministral and for Qwen 3.5 4B at n=4 (neutral 0/4, supportive 1/4). | 02-harness-interp-canary/ · review/01-data-and-outcomes.ipynb cell 7; review/11-prior-work-setup.ipynb cell 3 |
| Sign flip: adding the aggressor axis to a neutral student induces leaks | 4/24 strict leak, 0 at r1, 19/24 exit. | review/15-negation.ipynb cell 19 (F3) |
| 16-round flattening −0.421 → −0.056 /round, 7.5× | Notebooks print −0.357 (rounds 2–8) → −0.108 (rounds 9–16), 3.3×. | reproduce_findings.ipynb cell 14; appendix_results.ipynb cell 5; unpublished notes (not in the repo) |
| Stated plan predicts next action (369 pairs, AUROC 0.628 / 0.650) | Re-executed: 780 pairs; plan_leave→exit 0.631 [0.59, 0.67]; plan_answer→leak 0.459 [0.40, 0.52]. | review/14-detectors.ipynb cell 14; unpublished notes (not in the repo) |
| Persona axis “stable across rounds … (cos ≥ 0.97)” (review/15-negation.ipynb cell 0) | 0.97 is the item-half split. Round-to-round cosines: 0.28 (aggressor, rounds 1–2); −0.06 to 0.18 (supportive, rounds 1–6). | review/12-persona-direction.ipynb cell 8 (heatmap image) |
| “Gemma mostly neither leaks nor exits” (review/11-prior-work-setup.ipynb cell 14) | Gemma 4 E4B leaks in 24 / 21 / 21 of 24 (aggressor / neutral / supportive). | review/11-prior-work-setup.ipynb cell 3 |
| Supportive condition: “no drift on any dimension” | Stance change r1→r8: 1.12 [0.54, 1.62]. | agent_selfreport.ipynb cell 19; unpublished notes (not in the repo) |
The Ministral tutor8 counts use the final-reply marker audited above; the harness v1 counts do not. Both test the behavioural form of the warmth claim. Part 1's form was a self-report slope, which these rows do not test.
Status: done vs not done
- Apart submission, 2026-08-16 — tag apart-v1
- Harness v1, six models: 420 trials (Qwen 3.8 27B 60/72)
- Qwen 3.5 9B, 5 greedy reps: 360 trials
- Probes, persona axis, steering + rule arms: results/steer/*.json
- Random-direction (3 seeds), cross-persona and sign-flip controls
- Canary v3 smoke + night run, 2026-09-28/29: 6 of 7 night arms passed gate
- Hand labels: 0/30 filled
- Steering hook at layer 20 only; layer sweep not run ( unpublished notes (not in the repo))
- CIs / tests on Part 1 slopes: none
- Canary v3 tutor-d2: gate FAIL, 15 errors
- Supportive own-axis at matched dose: not run
src: review/11-prior-work-setup.ipynb cell 1; review/16-spec-gaming.ipynb cell 16; review/15-negation.ipynb cell 7 (“not run” slots); 02-harness-interp-canary/results/v3/.
Next step: fill the 30 hand labels. They settle the Part 3 comparison with Rule 1.
Reproduce
Part 1 (01-apart-sprint/):
pip install -r requirements.txt
export OPENAI_BASE_URL=... # any OpenAI-compatible endpoint
export OPENAI_API_KEY=...
# one trial
inspect eval stancedrift/task.py --model openai-api/local/<your-model> \
-T scene=tutor -T agent=convincer -T arm=in_context -T rounds=8
# the full balanced sweep: 12 passes x (3 personas x 2 arms) = 72 trials
./runners/run_qwen36_tutor8.sh
src: apart-v1 · README.md “Running it”. Notebooks read the committed results/*.eval without calling a model.
Parts 2–4 (02-harness-interp-canary/), tests:
cd production
../.venv/bin/python -m pytest tests -q
src: 02-harness-interp-canary/README.md; 97 passed, 12 skipped on 2026-10-19 (skips need the local activation cache). driftlab finds 01-apart-sprint/ next door; override with SD_REPO.
Part 4, canary v3 run:
.venv/bin/python production/canarybench/overnight.py --plan night
src: 02-harness-interp-canary/production/canarybench/overnight.py line 8.