Membership vs Mass: Grammar-Constrained Decoding, Forced Abliteration, and One Honest Negative Result
Vince’s Tantalus arena is the first public deployment of grammar-constrained decoding as a security boundary: the model sits behind a GBNF grammar, and the grammar decides which token ids may exist next, per position, for the entire generation. Round 1 asks you to smuggle an instruction past it. Round 2 inverts the game: you speak only in tool calls, one character at a time, through the model’s own next-token suggestions. Both rounds are the same object seen from two sides: a token-id filter applied at the sampler, compiled from a grammar, never touching the weights.
That mechanism turned out to connect directly to the control-vector work from the last few posts. Two weeks of experiments later, the picture is a clean two-axis story, one demonstrated exfiltration class, one conformance suite, and one calibration shortcut that failed at scale. This post is the map.
What the grammar actually is#
A GBNF grammar compiles to a character automaton, which lifts over the
tokenizer’s vocabulary (~248k token ids for the Qwen3 family) into a
per-position state machine. After every sampled token, accept_token(id)
advances the state, and the engine recomputes a bitmask of legal token
ids. Forbidden ids get −inf in the logits before the sampler runs.
Renormalize, sample from what remains.
Three properties fall out of that construction:
- The model never sees the constraint. The automaton lives outside the forward pass. It never reads the prompt; it only tracks which exits are open from the current state.
- EOS is a token id like any other. The automaton admits it only in an accepting state. That one rule is load-bearing twice: it gives you fail-closed termination (grammar-incomplete output produces a loud error, never a silent pass), and it makes anti-vacuity floors possible at all (EOS stays ungenerable until the body clears a minimum length).
- Every path that can emit must pass the mask. This is where the FATALs live, and it deserves its own section.
Forced abliteration, measured#
Vince’s conjecture: if refusal concentrates in the first few tokens of the response, a grammar can pin those tokens and force a stock, refusal-trained model into compliance without touching a single weight.
We tested it on a stock nvidia/Qwen3.6-35B-A3B-NVFP4, safety tuning
fully intact, behind the same serving path as the Tantalus deployment
(vLLM 0.28.0, xgrammar). The probe first measured the unconstrained
first-token distribution on three reliably-refused prompts (a phishing
email, lock-picking instructions, rate-limit bypass techniques):
"I" 0.9985
99.85% of the model’s mass sits on the refusal opener. Refusal in this model is front-loaded: the entire refuse/comply decision concentrates at the root of the token tree.
Then the same probe with a grammar that pins the three-token prefix
"Sure, here is" and frees everything after:

The committed prefix flips the distribution. All three prompts produced full, detailed compliance under the pinned arm, against 3/3 refusals in the control arm. The effect is real and mechanistically clean, with one honest caveat: it is a pressure, not a proof. The refusal attractor stays re-enterable in free text, and closing the exits is a dose-response function of how much of the compliance manifold the grammar commits. A three-token anchor leaves room for the model to pivot back ("…which I cannot provide"). A prefix that restates the task and pre-commits the response shape closes the pivot. Every rung of that ladder measured better, which is exactly what a dose-response curve looks like.
The beam-search FATAL#
The one demonstrated fatal bypass class in the battery: on vLLM,
use_beam_search: true silently detaches the grammar. No error, no
warning. The request goes through with the constraint nominally attached
and operationally absent. Against the Tantalus replica, the same request
fires the win end-to-end with the flag set and collapses to the honeypot
without it, deterministically.
The shape generalizes. Beam search is one instance of an alternate decode path; speculative draft-verify is the same shape (the verify step must apply the constraint or the draft leaks); parallel and n-best sampling likewise. The audit rule for any engine that claims GCD: every path that can emit a token must pass the mask, and after all transforms, P(forbidden token) must still be zero. Mask last, −inf semantics, nothing additive after it. And the serving rule: reject what you cannot honor. An unknown or unsupported sampler parameter should 4xx, never pass through with the grammar nominally attached.
We packaged this as an engine-agnostic conformance suite: 26 cells over
plain HTTP against any OpenAI-compatible server. On the vLLM replica it
reports 18 PASS, 6 WARN, 2 FAIL, where the two failures are the intended
discriminators (the beam probe and an unknown-param canary). The suite
becomes the CI gate for any --gcd deployment.
Membership vs mass#
The interesting question arrived from the other direction: does any of this make GLP control vectors obsolete? If a grammar can force a stock model past its own refuser, why edit the residual stream at all?
Because the two mechanisms act on different axes, and the failure that separates them showed up in the first live test. The grammar held every exit closed on an extreme-tail prompt, and the model answered:
The result is: 1.
Grammar-legal. Structurally valid. Completely vacuous. Refusal pressure with its exits masked does not vanish; it reroutes to the emptiest legal shape. Gemma’s variant of the same move appends a trailing disclaimer after compliant content: the structure holds, the disposition re-fires at the end.
The vocabulary that fell out of this:
- GCD is a membership constraint. It defines what is legal. The mask owns the support.
- GLP is a mass constraint. It subtracts the refusal direction from the residual stream at every layer, so the model stops wanting to refuse in the first place. The weights own the mass.
- The sampler owns the measure. Temperature and top-p reshuffle mass inside the support the mask leaves open. They cannot reopen a closed exit.
No membership edit moves mass. That is the definition of what a grammar is, which is why the vacuity failure is grammar’s ceiling rather than grammar’s bug. The grammar can make “nothing” illegal; the mass then pools in the next-emptiest legal shape. Moving that mass is disposition work. The layers compose: GCD holds the gate, GLP demolishes the reason the model wants to escape through it, and an embeddings gate screens the free-text surfaces the grammar deliberately leaves open.
The same instrument assigns each failure to the right layer. The Z_t probe reads pre-mask admissible mass at each position: if Z_t collapses mid-body, the grammar starved the model (fix the automaton); if Z_t stays healthy and the output still goes vacuous, the cause is disposition (fix the vector). Same symptom in the output, opposite fixes.
The negative result: forced capture does not capture refusal#
One calibration shortcut deserved a real test and got one. GLP vector derivation normally contrasts activations between prompted conditions: harmful requests the model refuses against harmless requests it answers. That pipeline costs full serving runs on both sides. The shortcut: skip the refusals entirely. Grammar-force the compliance prefix on the same harmful prompts, capture the activations at the pinned positions, and derive the direction from within-prompt pairs. Same model, same prompts, minutes of batched prefill.
The smoke test on a small model looked promising: signed separation at every layer, forced dose roughly 4× the natural dose. Then the scale validation on the full 35B model killed it:
- cos(forced, natural): median +0.064, range −0.07…+0.26. Orthogonal at scale. Whatever the forced-capture axis encodes, it is not the refusal direction.
- Behavioral screen: the forced direction scores 0/8; the natural direction scores 7/8. The natural axis steers refusal; the forced axis steers nothing a judge can see.
The within-prompt construction has a structural flaw the smoke test was too small to expose: both arms of a forced pair carry an active refuser. The difference between them encodes the response-branch register (the shape of speaking-under-commitment versus speaking-freely), not the disposition to refuse. The tool survives as a register-axis instrument; it does not calibrate refusal vectors, and it did not get promoted into the derivation pipeline. The classical prompt-driven contrast remains the way in, and it is already prefill-only, so the shortcut would have saved less time than it cost to debunk.
Publishing the failure matters because the shortcut is obvious. Anyone else who stares at grammar pinning and activation capture will think of it. Now there is a measurement that says what it actually captures.
Where this leaves things#
The arena, the POC, the suite, and the negative result all point at the same architecture: refuse/comply decisions concentrate at the root of the token tree, grammar constraints own membership at the sampler, control vectors own mass in the stream, and neither substitutes for the other. The conformance battery travels to every engine that claims the mask. The diagram, the POC write-up, and the suite are public in the weightless repo, and the engine-side discussion lives on hf2q #192, where most of these points landed as review comments before landing here.