lemma 0.9.2

A pure, declarative language for business rules.
**Rules and unless: last matching clause wins**

Write default expression, then: `unless <condition> then <result>`. Evaluated in source order. If multiple match, **bottommost wins**. Order general first, specific overrides last.

Use **snake_case** rule names. Boolean rules as predicates: `is_eligible`, `can_ship`. Decompose logic into pipeline of named rules. No opaque single expressions.

**Example F — overlapping unless (last wins)**

```lemma
spec vip_discount

data qty: number
data is_vip:   boolean

rule discount: 0%
  unless qty >= 10  then 10%
  unless qty >= 50  then 20%
  unless is_vip          then 25%
```

VIP customer ordering 75 items gets **25%** (not 20%). Both `qty >= 50` and `is_vip` match; bottommost wins.

**Example G — progressive unless chain**

```lemma
spec rules_and_unless

data is_premium:   yes
data base_price:   number -> minimum 0
data customer_age: number -> minimum 0 -> maximum 120
data qty:          number -> minimum 0

rule total_before_discount:
  base_price * qty

rule discount_percentage:
  0%
  unless qty >= 10 then 10%
  unless qty >= 20 then 15%
  unless is_premium   then 20%

rule discount_amount:
  total_before_discount * discount_percentage

rule total_after_discount:
  total_before_discount - discount_amount

rule shipping_cost:
  15
  unless total_after_discount >= 100 then 10
  unless total_after_discount >= 200 then 0

rule final_total:
  total_after_discount + shipping_cost
```

Tiered discounts, derived rules referencing prior rules, unless on computed values.

**Example H — decomposed shipping pipeline**

```lemma
spec shipping_policy
uses lemma units

data destination_country: text
  -> option "NL"
  -> option "BE"
  -> option "DE"
  -> option "FR"
  -> suggest "NL"

data customer_tier: text
  -> option "standard"
  -> option "silver"
  -> option "gold"
  -> option "platinum"
  -> suggest "gold"

data destination_region: text
data is_expedited:       boolean
data is_hazardous:       boolean
data is_po_box:          boolean
data item_weight:        units.mass
data order_total:        number -> minimum 0

rule base_shipping_rate: 35
  unless destination_country is "NL" then 22
  unless destination_country is "BE" then 25
  unless destination_country is "DE" then 28
  unless destination_country is "FR" then 30

rule weight_surcharge: 0
  unless item_weight > 5 kilogram  then 7.5
  unless item_weight > 20 kilogram
    then veto "Item too heavy for standard shipping"

rule po_box_fee: 0
  unless is_po_box then 5

rule expedited_fee: 0
  unless is_expedited                           then 25
  unless is_expedited and item_weight > 10 kilogram then 45

rule hazardous_fee: 0
  unless is_hazardous then 50
  unless is_hazardous and destination_country is not "NL"
    then veto "Cannot ship hazardous materials internationally"

rule customer_discount: 0%
  unless customer_tier is "silver"   then 10%
  unless customer_tier is "gold"     then 20%
  unless customer_tier is "platinum" then 30%

rule free_shipping_eligible:
  order_total >= 100 and destination_country is "NL"

rule shipping_before_discount:
  base_shipping_rate + weight_surcharge + po_box_fee
  + expedited_fee + hazardous_fee

rule shipping_discount_amount:
  shipping_before_discount * customer_discount

rule final_shipping:
  shipping_before_discount - shipping_discount_amount
  unless free_shipping_eligible then 0

rule ships_to_location: true
  unless is_po_box and is_hazardous
    then veto "Cannot ship hazardous materials to PO boxes"
  unless destination_region is "Svalbard"
    then veto "Shipping not available to Svalbard"

rule Summary: "Standard shipping"
  unless free_shipping_eligible
    then "Free shipping (order over €100)"
  unless is_expedited then "Expedited shipping"
```

Each fee is distinct rule. `item_weight` uses `units.mass`. Veto clauses placed last in `weight_surcharge` and `ships_to_location`. Eligibility separated from amount rules.