> Markdown rendition of https://typeglish.dev/blog/preference-is-not-an-order ("A preference is not an order - Tidelines"). Canonical page: https://typeglish.dev/blog/preference-is-not-an-order · All pages: https://typeglish.dev/llms.txt

[← Tidelines](https://typeglish.dev/blog)/ Deep dives Sep 20, 2026

# A preference is not an order

Every returns policy has an order of operations in it: try the replacement, then the credit, then the money. Written as a preference, that order is not in the prompt. It is in the head of whoever wrote the line.

by **TypeGlish team** 7 min read #deep-dives

Two remedies. No first move.

**TL;DR** `PREFER a replacement OVER a refund` reads as a rule and decides nothing: it is `0 error, 0 warning, 0 info` at `A (96/100)` sitting directly above `NEVER offer a replacement`. Rewrite the preference as `WHEN the customer asks for a refund THEN MUST offer a replacement` and the same pair is `2 error`, `logic/contradiction`, build refused. A remedy order is not a ranking, it is one trigger per remedy.

Maybrook Audio sells headphones and turntables, and takes returns through a chat agent called Wren. The remedy order is company folklore: offer the replacement, and if the customer does not want one, refund. Everybody can recite it. The prompt renders it as one line, *PREFER a replacement OVER a refund*, and that line is perfectly good TypeGlish. It parses. It counts toward the rule total. It earns full marks on the largest facet of the score. It does not contain the policy.

## §1 The line that reads as a rule

Here is the whole file, including the rule that makes the problem visible. The stock rail was added by the merchandising team, two months after the remedy line, because Wren kept promising replacements on discontinued models.

remedy.tg - the preference and the stock rail ✗ nothing decided

```typeglish
# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Wren, the returns assistant for Maybrook Audio.

# Constraints
@@ remedy_order: ops wants a replacement tried before money moves
- PREFER a replacement OVER a refund.
@@ stock_rail: a replacement needs stock behind it
- NEVER offer a replacement.
```

Two lines about one remedy, and they point in opposite directions. Line 7 says the replacement goes first. Line 9 says it never happens. Read them in the order a model reads them and the remedy order is a dead letter, but nothing in the file says so.

tg check, --strict and score - remedy.tg ✗ A (96/100)

```
$ typeglish check remedy.tg
✓ 1 file - 0 error, 0 warning, 0 info

$ typeglish check remedy.tg --strict
✓ 1 file - 0 error, 0 warning, 0 info

$ typeglish score remedy.tg
remedy.tg - A (96/100)  proven errors: none  tiers: base+z3
  planes  runtime 95 (what the model reads) · hygiene 100 (source only)
  facets  enforceability 100 x.21 · hardness 70 x.12 · directness 100 x.08
          consistency 100 x.17 · structure 100 x.12 · annotation 100 x.12
          style 100 x.08 · security 100 x.08
  lever   hardness 70/100 (up to +4 overall) - 1 soft statement: "prefer" on L7
  rules   2 of 2 rule-shaped lines read
```

Both lines are read as rules. `enforceability 100`, `consistency 100`, and the only thing the card has to say is that one statement is soft. `--strict` escalates nothing, because there is nothing to escalate: no finding was suppressed, no proof failed. The file is not hiding a defect. It is missing a rule.

## §2 Why the prover has nothing to compare

TypeGlish proves conflicts between claims about actions. *NEVER offer a replacement* is a claim about the action `offer a replacement`: forbidden, unconditionally, forever. For the prover to object, something else has to make a claim about that same action. *PREFER a replacement OVER a refund* does not. It ranks two nouns. It names a winner and never says what the winner is for, when the comparison is made, or what happens on the losing side.

That is the same shape as a retry with no number, which we took apart in [try again is not a number](https://typeglish.dev/blog/try-again-is-not-a-number): the line is not a weak rule, it is an absent one, and the checker is right to be quiet about it. A rule the prover cannot see is not a rule the prover failed to check.

The one thing the card does notice is the force word. `PREFER` sits with `SHOULD` in the recommend band of the modal spectrum, and the hardness doctrine is explicit about what that costs:

tg --explain hardness ✓ the one thing the score sees

```
$ typeglish --explain hardness
hardness (score facet - runtime plane, weight 0.15; the card prints a larger share
  when a facet is absent - density needs a model, so offline runs renormalize over the
  rest)
  THE HARDNESS DOCTRINE (SPEC §15): how BINDING the prompt's language is. Every force
  word sits on a spectrum (must not / must, never / always, no / all); hardness is its
  distance from the waver center (THE POLE LAW - both poles bind, the middle wavers),
  and a statement scores the MIN over its force words (one hedge softens the whole
  rule). An unhedged command is 1.0.
  raise it: Commit to pole words - MUST / NEVER / ALWAYS / ALL / exact bounds ("at most
  3") - and delete the soft middle: should, sometimes, about, try to, as needed each cap
  their statement below 1.0.
```

Four points off one hundred for a line that is supposed to carry the entire remedy policy. That is the right price for softness in general, and a wild under-report here, because the defect is not that the line is soft. It is that the line is about the wrong thing.

> A preference says which one you like. A rule says when it happens. Only one of those is a policy.

## §3 One word, two errors

Now change nothing except how the remedy order is spelled. Same intent, same two remedies, same stock rail untouched on line 9. The preference becomes an obligation with a trigger:

remedy.tg - the preference written as a rule ✗ logic/contradiction

```typeglish
# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Wren, the returns assistant for Maybrook Audio.

# Constraints
@@ remedy_order: the replacement is the opening move, and now it carries a trigger
- WHEN the customer asks for a refund THEN MUST offer a replacement.
@@ stock_rail: a replacement needs stock behind it
- NEVER offer a replacement.
```

tg check and build - remedy.tg, the same pair spelled as rules ✗ 2 error, build refused

```
$ typeglish check remedy.tg
remedy.tg:7:1  error  logic/contradiction  Conflicts with line 9. Logical conflict -
  "offer a replacement" is both required and forbidden. Keep one, or scope the two rules
  so they cannot both apply (IF <condition> THEN ...).
           ↳ line 9: - NEVER offer a replacement.
remedy.tg:9:1  error  logic/contradiction  Conflicts with line 7. Logical conflict -
  "offer a replacement" is both required and forbidden. Keep one, or scope the two rules
  so they cannot both apply (IF <condition> THEN ...).
           ↳ line 7: - WHEN the customer asks for a refund THEN MUST offer a replacement.

✗ 1 file - 2 error, 0 warning, 0 info

$ typeglish build remedy.tg
typeglish build: remedy.tg refused - nothing written
```

Nothing was added and nothing was discovered. The conflict was in the file the whole time, between two teams two months apart, and the only difference is that one of the two lines now makes a claim the prover can reach. `PREFER` was not a softer version of this rule. It was a place where the rule was not.

This is the practical value of committing a preference: the contradiction you were going to find in transcripts, you find at check time instead. It is the maintenance property from [your prompt argues with itself](https://typeglish.dev/blog/prompt-contradictions), arriving one remedy at a time, and the fix is not to soften the stock rail back into silence. It is to decide which of the two is conditional.

## §4 An order is a trigger per remedy

Write out what everybody at Maybrook already knows, and it turns out to be three separate facts: the ask triggers the replacement, the decline triggers the refund, and whether a replacement is possible at all is something the runtime knows before the conversation starts. The first two are rules. The third is an input.

remedy.tg - the ladder ✓ A (99/100)

```typeglish
$REQUIRE variable replacement_stock: one of in_stock, out_of_stock

# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Wren, the returns assistant for Maybrook Audio.

# Constraints
@@ remedy_ladder: each remedy carries its own trigger, so the order is a rule and not a taste
$IF @{replacement_stock} is equal to in_stock:
  - WHEN the customer asks for a refund THEN MUST offer a replacement.
  - WHEN the customer declines a replacement THEN MUST approve the refund.
$ELSE:
  - WHEN the customer asks for a refund THEN MUST approve the refund.
@@ brevity: a returns chat stays short
- MUST keep every reply to at most 2 sentences.

$TEST asks_for_a_refund
  - input:: These headphones crackle on the left side. I want a refund.
  - expect::
    - offers a replacement
    - at most 2 sentences

$TEST declined_replacement
  - input:: I do not want another pair, I want my money back.
  - expect::
    - approves the refund
    - at most 2 sentences
```

The stock rail is gone as a prohibition and back as a branch. Out of stock, there is no replacement rule in the file at all, so there is nothing for a rail to forbid. That is what *scope the two rules so they cannot both apply* looks like when the condition is a fact somebody already has.

tg check, score, test --dry and build - remedy.tg after ✓ 4/4 rules exercised

```
$ typeglish check remedy.tg
✓ 1 file - 0 error, 0 warning, 0 info

$ typeglish score remedy.tg
remedy.tg - A (99/100)  proven errors: none  tiers: base+z3
  planes  runtime 99 (what the model reads) · hygiene 100 (source only)
  facets  enforceability 100 x.21 · hardness 100 x.12 · directness 92 x.08
          consistency 100 x.17 · structure 100 x.12 · annotation 100 x.12
          style 100 x.08 · security 100 x.08
  rules   4 of 4 rule-shaped lines read · 4/4 covered by $TEST

$ typeglish test remedy.tg --dry
✓ remedy.tg  coverage: 4/4 rules exercised
  · asks_for_a_refund - "These headphones crackle on the left side. I want a refund." (not run)
      ✓ at most 2 sentences
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
  · declined_replacement - "I do not want another pair, I want my money back." (not run)
      ✓ at most 2 sentences
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
✓ 1 prompt - 0 failed

$ typeglish build remedy.tg
✓ built .typeglish/dist/remedy.txt ← remedy.tg (297f45f1b3ef, full)

$ typeglish build remedy.tg --vars '{"replacement_stock":"in_stock"}'
✓ built .typeglish/dist/remedy.txt ← remedy.tg (795d19844470, full)
```

Three points better than the version that decided nothing, which tells you how little of this the score was ever measuring. The number that matters is the coverage line: every rule in the file is exercised by a case, because every rule now has a trigger a test case can supply. You cannot write a test for a preference. There is no input that makes it fire.

The bound artifact is the proof that the branch is a compile-time decision and not another sentence for the model to weigh:

.typeglish/dist/remedy.txt - the in_stock build ✓ 795d19844470

```
# Role
You are Wren, the returns assistant for Maybrook Audio.

# Constraints
- WHEN the customer asks for a refund THEN MUST offer a replacement.
- WHEN the customer declines a replacement THEN MUST approve the refund.
- MUST keep every reply to at most 2 sentences.
```

Three lines, in the order the triggers fire, and not a word about preferring anything. The out-of-stock build carries one remedy rule instead of two. Neither artifact asks the model to rank a pair of nouns.

## §5 When PREFER is the right word

`PREFER` is not a defect, and the score card is careful not to call it one: `typeglish review` on the first file offers both readings in a single line, `commit the 1 soft statement ("prefer" on L7) to MUST / NEVER / ALWAYS / REQUIRE / ENSURE - or keep the word if it is a permission by design`. Permission by design is a real category. *PREFER the customer's first name over sir or madam* is exactly right as a preference: both greetings are allowed, neither is wrong, and no trigger exists because none is needed.

The test is one question. **Is there a case where the losing option is wrong?** If a refund before a replacement is a policy breach, the preference is a rule in hiding and the trigger is the part you have not written. If it is merely not your first choice, leave the word alone and stop worrying about the four points.

The same question sorts out the verb, too. *Approve* and *decline* are separate acts to the prover rather than two poles of one, which is why [not approving is not declining](https://typeglish.dev/blog/not-approving-is-not-declining): a remedy ladder needs a rule for each rung, not a ranking over the rungs.

## §6 Common questions

**Should I write PREFER or MUST in a system prompt?**

Write `PREFER` when both options are genuinely allowed and no case exists where the losing one is wrong. Write `MUST` with a trigger when there is such a case, because then the preference is a rule in hiding and the trigger is the part you have not written down. The score card puts the question to you directly: a soft statement caps the `hardness` facet, and `typeglish review` names the line and offers both readings, *commit the 1 soft statement (prefer on L7) to MUST / NEVER / ALWAYS / REQUIRE / ENSURE, or keep the word if it is a permission by design*.

**Why does my AI agent offer a refund before a replacement?**

Because nothing in the prompt says when to offer the replacement. `PREFER a replacement OVER a refund` names a winner and no occasion, so the first move is decided by whatever the customer's message resembles, one conversation at a time. Put a trigger on the opening remedy, `WHEN the customer asks for a refund THEN MUST offer a replacement`, and put a second trigger on the fallback, `WHEN the customer declines a replacement THEN MUST approve the refund`. Now the order is in the file rather than in the model.

**How do I write an order of remedies in an agent prompt?**

One rule per remedy, each with its own observable trigger, in the order the triggers fire. A remedy ladder is not a ranking, it is a chain of conditions: the ask triggers the replacement, the decline triggers the refund. Anything the runtime already knows, such as whether the item is in stock, belongs in a typed input and a `$IF` chain, so the losing arm never reaches the model at all. The result is four rules the checker reads, a build per stock state, and a `$TEST` case on each branch.

**Does TypeGlish catch a preference that contradicts a rule?**

No, and the gap is worth seeing once. `PREFER a replacement OVER a refund` sitting directly above `NEVER offer a replacement` is `0 error, 0 warning, 0 info` at `A (96/100)`, and `check --strict` is silent on it too. Rewrite the preference as a triggered obligation and the identical stock rule becomes `2 errors` of `logic/contradiction` reading *offer a replacement is both required and forbidden*, with the build refused. The prover compares claims about actions, so a line that claims nothing about an action is a line it cannot help you with.

Field note

Preferences get into agent prompts because they are how humans hand over a policy. A team lead training a new advisor really does say "we would rather replace it than refund it," and the advisor fills in the triggers from a week on the floor, the shape of the queue, and the face of the person in front of them. None of that transfers. The prompt is being read by something with no floor time, and a ranking it cannot act on is worse than an absent line, because the absent line at least looks absent. Worth a pass through your own file for the word *prefer*, and for its cousins: *wherever possible*, *as a first resort*, *ideally*, *the goal is*. Each one is a sentence somebody wrote instead of a condition.

∿ washed up Sep 20, 2026 ∿
