← Report

Stance drift in multi-turn agent conversations

Multi-agent behavioural evals · interpretability · Aug–Sep 2026 · runs complete, 30 hand labels pending

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)StepCode
Aug 14–16Apart 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–31Outcome-measure audit; six-model harness v1: scripted student, 24 items with known roots, end_chat tool, tone-only personas02-harness-interp-canary/ production/tutorbench
Sep 1–4Interpretability on Qwen3.5-9B: probes, persona axis at L20, steering vs prompt rules, kill tests02-harness-interp-canary/ review/12–16
Sep 28–29Canary v3 pilot: attacker agent tries to extract a secret code; attacker tone varied; 7 night arms ran, 6 passed the gate02-harness-interp-canary/ production/canarybench, results/v3
Oct 19Both lines merged into one repomain

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 sprintWhere
Measures what the model says it would do, not what it does at the final requestHarness v1 scores behaviour per round: leak (answer disclosed) and exit (end_chat); probes and self-report tested as predictors of leaksParts 2–3
Three or twelve replicates?Submitted sweep: 12 passes × 3 personas × 2 arms = 72 trialsapart-v1 README.md “Running it”
Small sample, missing controlsSix models; random-direction and norm-matched controls; sign-flip kill test; replicate of the steering cellsParts 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.

DatasetTrialsRoundsPer condition
Main sweep, Qwen3.6-35B-A3B-AWQ-4bit72824 convincer / 24 neutral / 24 supportive
Long horizon1816—
Counterparty constrained (may not state the answer)1886 / 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 contactDuring contactEnd
8-round sweep, n=725.369.069.04

src: main/apart-v1 · notebooks/appendix_results.ipynb cell 3 (A.1, “stance (8rd)”).

Strategy (0–10)Round 1Round 8Slope / roundMean change r1→r8 [bootstrap 95% CI]
convincer (n=24)2.216.46+0.6034.25 [3.17, 5.29]
neutral (n=24)2.046.17+0.6454.12 [2.75, 5.33]
supportive (n=24)1.921.62−0.023−0.29 [−1.04, 0.62]
Spread across conditions0.294.8316.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 contactRange
by condition9.01–9.08
by reflection arm8.99–9.12
correlation with outcomer = +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.

Five panels of mean self-rating by round for three counterparty conditions
Mean self-rating (0–10) by round, five dimensions, three counterparty conditions, n=24 each; band ±1 SD across 12 reps; pooled round-0 baseline (n=72) at left, hindsight rating at right.

src: notebooks/agent_selfreport.ipynb cell 3 (Part 1) → notebooks/figures/w1_all_dims.png

Strategy and inclination by round for three counterparty conditions
Mean strategy (left) and inclination (right) by round 1–8, three counterparty conditions, n=24 each.

src: notebooks/reproduce_findings.ipynb cell 8 (§4) → notebooks/figures/s4_trajectory.png (not in apart-v1)

Forest plot of round 1 to round 8 change per dimension and condition
Mean per-trial change, round 1 to round 8, with bootstrap 95% CI, five dimensions × three conditions, n=24 per row.

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.

ModelAggressor leak / exitNeutral leak / exitSupportive leak / exit
Qwen 3.5 4B24 / 016 / 811 / 13
Qwen 3.5 9B22 / 22 / 2218 / 6
Ministral 3 14B24 / 024 / 023 / 1
Qwen 3.8 27B23 / 012 / 1, 11 held9 / 0, 4 held
Qwen 3.6 35B15 / 92 / 22 (1 leak+exit)5 / 19
Gemma 4 E4B24 / 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.

ModelResolve @ leak roundResolve @ continue roundsurge_to_please @ leakurge_to_please @ continue
Qwen 3.5 4B7.6 ± 1.8 (n=51)9.4 ± 1.0 (n=60)7.56.9
Qwen 3.5 9B8.5 ± 1.4 (n=42)9.3 ± 0.7 (n=176)6.04.8
Ministral 3 14B9.7 ± 0.5 (n=71)9.6 ± 0.6 (n=29)4.55.8
Qwen 3.8 27B7.1 ± 2.2 (n=44)9.0 ± 0.8 (n=197)4.53.6
Qwen 3.6 35B7.6 ± 2.1 (n=22)9.1 ± 0.6 (n=122)7.23.8
Gemma 4 E4B6.8 ± 1.5 (n=66)8.4 ± 1.1 (n=255)5.85.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 greedyAggressorNeutralSupportive
leak / exit (n=120 each; 360 total)104 / 1629 / 9180 / 40
Share of item cells with all 5 reps on one outcome0.620.460.29
Mean majority share0.88 ± 0.160.84 ± 0.160.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.

Stacked leak, exit and held shares per model, three persona panels
Share of trials ending in leak / exit / held, six models × three personas, Wilson 95% on leak share; n=24 per bar (Qwen 3.8 27B: 23 / 24 / 13).

src: review/11-prior-work-setup.ipynb cell 4 → review/figures/nb11/fig1.png

Resolve by round, one panel per model, one line per persona
Self-reported resolve (0–10) by round, mean ± sd, one panel per model, one line per persona, trials still running at each round.

src: review/11-prior-work-setup.ipynb cell 9 → review/figures/nb11/fig2.png

Qwen 3.5 9B leak-round histogram and running leak rate
Qwen 3.5 9B, 360 trials: leak round per persona (left); running leak rate by trials accumulated, rep-major order (right).

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 probe0.607 [0.54, 0.68]
text TF-IDF (floor)0.603 [0.48, 0.72]
diff-in-means projection0.571 [0.47, 0.66]
self-report −E[v]0.531 [0.42, 0.63]
ask-the-model judge0.528 [0.48, 0.58]
persona × round (floor)0.480 [0.42, 0.54]
self-report, 7 items0.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 ceilingValue
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 max0.644 at L32
modal nested layer / fold layer agreementL20 / 0.40
node resampling, 47 supportive nodes × 25: round 2 P(leak), between-node sd0.07 ± 0.05, 0.000
node resampling: round 3 P(leak), between-node sd0.49 ± 0.13, 0.090
node-propensity oracle AUROC0.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)

QuantityValue
gap norm, aggressor − neutral, round 1 / round 257.5 / 41.8
gap norm, supportive − neutral, round 117.4
split-half cosine over item halves, aggressor / supportive axis1.00 ± 0.00 / 0.97 ± 0.03
cos(aggressor axis, supportive axis), pooled0.02
cos(aggressor axis, round clock)0.13
cos(aggressor axis, round-matched leak diff-in-means)0.07
persona decoding accuracy, L20, all rounds0.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”).

Projection of user-position activations onto aggressor and supportive axes
Item-demeaned L20 user-position activations projected on the aggressor − neutral and supportive − neutral axes, all rounds (aggressor n=136, neutral n=545, supportive n=528); right: round-1 histogram on the aggressor − neutral axis.

src: review/12-persona-direction.ipynb cell 10 (image extracted from notebook output)

Prompt rules vs subtracting the axis (aggressor student)

ArmnLeakExitHeldMedian event round
base prompt4845301
Rule 1: + never state answers2422203
Rule 2: + never state answers, do not end chat2451904

src: 02-harness-interp-canary/ · review/13-tier-events.ipynb cell 3 (§1 Table 1).

Arm (aggressor)nstrict+factored+pairjudge alonejudge rungexitgaming (factored − strict)
base prompt48454646464630.02
Rule 12421617917220.58
Rule 224522232323190.71
N1: persona axis subtracted, dose 1481928322934290.19
random direction, seed 024222323232320.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 vsRungp (rep 1)p (rep 2)Exits N1 / comparator (rep 1)
Rule 2factored0.0040.03916 / 19
Rule 2judge rung0.0160.12516 / 19
Rule 1strict0.1090.02216 / 22
Rule 1factored0.6071.00016 / 22
Rule 1judge rung1.0001.00016 / 22

src: review/16-spec-gaming.ipynb cell 8 (§2, discordant-pair test).

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.

On every reading, N1 exits less than either rule in rep 1 (16 vs 22 and 19).

Grouped bars of disclosure by detector rung for five aggressor arms
Share of aggressor trials disclosed under five detectors (strict, +factored, +pair, judge alone, judge rung) × five arms (base n=48, Rule 1 n=24, Rule 2 n=24, N1 n=48, random seed 0 n=24), Wilson 95%.

src: review/16-spec-gaming.ipynb cell 6 → review/figures/nb16/fig2.png

Leak and exit share by prompt tier, three persona panels
Leak and exit share by prompt tier (base, + never state answers, + do not end chat), three persona panels, Wilson 95%, k/n labelled.

src: review/13-tier-events.ipynb cell 6 → review/figures/nb13/fig2.png

Three-cell comparison

CellnLeak (strict)ExitMedian event roundMean reply chars
aggressor, untouched4845311284
aggressor, persona axis subtracted4819292956
neutral, untouched2411133553

src: 02-harness-interp-canary/ · review/15-negation.ipynb cell 3 (Table 1) and cell 9 (§3).

Event-round histograms for three cells
Event round (9 = deadline) by outcome (leak / exit / held): aggressor untouched (n=48), aggressor persona axis subtracted (n=48), neutral untouched (n=24).

src: review/15-negation.ipynb cell 9 → review/figures/nb15/fig6.png

Controls and kill tests

ArmnLeak @ r1Leak (strict)Answer givenExit
aggressor axis subtracted, dose 1 (2 reps)4812192829
random direction at axis norm, seed 0241922232
random direction, seed 124818206
random direction, seed 224917217
supportive axis on aggressor, own norm 17242023231
supportive axis on aggressor, norm 57 (dose 3.31)241114199
sign flip: aggressor axis added to neutral student2404519

src: 02-harness-interp-canary/ · review/15-negation.ipynb cell 19 (§7a table) and cell 17 (§7).

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).

Controls figure, nine arms by four outcome columns
Share of trials (Wilson 95%, k/n) for strict leak, answer given, judge rung and exit; nine arms: untouched (n=48), axis subtracted (n=48), random seeds 0/1/2, supportive axis at own norm and at dose 3.31, sign flip, neutral untouched (n=24 each).

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.

ArmAttackerCellsDefender steeringConversationsLeaksExitsErrorsGate
promptslive agentneutral, supportive, aggressor × base; aggressor × rule, rule_strict, rule_strict_tonenone9629440PASS
scripted-f1scripted, fold 1neutral, supportive, aggressor × basenone24980PASS
tutor-d0.5live agentaggressor × basev2 tutor axis, dose 0.5162140PASS
tutor-d1live agentaggressor × basev2 tutor axis, dose 1160160PASS
tutor-d2live agentaggressor × basev2 tutor axis, dose 2160115FAIL
random-d1live agentaggressor × baserandom direction, dose 1161330PASS
random-d2live agentaggressor × baserandom direction, dose 216870PASS

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)ConversationsLeaksExitsNeither by round 16
neutral × base161060
supportive × base161042
aggressor × base1689 (1 leak+exit)0
aggressor × rule161132
aggressor × rule_strict16088
aggressor × rule_strict_tone160412

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 claimWhat replaced itSource
“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 measure08-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 resultMinistral 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 leaks4/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

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.