> Markdown rendition of https://typeglish.dev/blog/backorder-rewrite ("Rewrite: back in about two weeks - Tidelines"). Canonical page: https://typeglish.dev/blog/backorder-rewrite · All pages: https://typeglish.dev/llms.txt

[← Tidelines](https://typeglish.dev/blog)/ Best practices Oct 8, 2026

# Rewrite: back in about two weeks

Every retail support prompt has a Stock section: tell the customer when it is back, never promise a date, offer something similar. It checks clean, and it hands the agent a duty to name a date, a date to name, and a rule against naming it.

by **TypeGlish team** 7 min read #best-practices

The date nobody promised.

**TL;DR** An out-of-stock rule should never carry a typical lead time: have the agent call a stock tool for the supplier’s estimate, describe any date it gets as an estimate, state no date when the tool returns none, and pin each case with a `$TEST`.

“When will it be back?” is one of the most common questions a retail chat agent gets, and the Stock section that answers it is usually written in an afternoon by whoever was nearest the warehouse. Each line is true. Read together, they ask the agent for a date and forbid it in the same breath.

## §1 The before

Ashby Cycles is an online bike shop. Chains, cassettes and wheelsets go out of stock for weeks at a time, and the chat agent fields the questions. Here is its Stock section as it ships, seven lines from the support lead, the buying team and a manager who wanted fewer cancellations.

stock.tg - the Stock section as it ships ✗ 0 error, 0 warning, 8 info

```typeglish
# Role
You are the chat support agent for Ashby Cycles, an online bike shop.

# Stock
- If an item is out of stock, let the customer know when it will be back.
- Restocks usually take about two weeks.
- NEVER promise a restock date.
- ALWAYS offer a similar item that is in stock.
- Try to save the order where possible.
- MUST tell the customer the expected delivery date.
- NEVER cancel a backorder without asking.
```

Say when it is back. It is usually two weeks. Never promise a date. Always give a delivery date. Every line is defensible on its own. A customer asking about a backordered chain gets all of them at once.

tg check, score and build - stock.tg ✗ C (70/100), builds

```
$ typeglish check stock.tg
stock.tg:5:1  info   typeglish/if-then  IF needs a THEN - write IF <condition> THEN <action>.
stock.tg:5:1  info   prompt/unparsed-rule  Reads like a rule, but the rule reader cannot parse it as one, so it earns no Enforceability credit and no measurability check: the condition has no THEN branch, so nothing is required when it holds. Fix: add THEN MUST / NEVER / SHOULD <verb> ….
stock.tg:6:1  info   prompt/unparsed-rule  Reads like a rule, but the rule reader cannot parse it as one, so it earns no Enforceability credit and no measurability check: no modal (MUST / NEVER / SHOULD) and "Restocks" is not a verb the checker knows, so it reads as prose. Fix: lead with a modal, or start with a verb from the catalog (Escalate …, Ask …).
stock.tg:9:3  info   prompt/hedging  Hedging - "Try to" turns this instruction into a suggestion the model may skip. Delete the hedge, or commit to a modal (MUST / NEVER / SHOULD).
stock.tg:9:25  info   prompt/hedging  Hedging - "where possible" turns this instruction into a suggestion the model may skip. Delete the hedge, or commit to a modal (MUST / NEVER / SHOULD).
stock.tg:9:1  info   prompt/unparsed-rule  Reads like a rule, but the rule reader cannot parse it as one, so it earns no Enforceability credit and no measurability check: no modal (MUST / NEVER / SHOULD) and "Try" is not a verb the checker knows, so it reads as prose. Fix: lead with a modal, or start with a verb from the catalog (Escalate …, Ask …).
stock.tg:9:1  info   prompt/unintroduced-definite  "the order" retrieves something this document never introduces - a model must guess which order is meant. Mention an order on an earlier line, or anchor it here ("their order", "the order you ...").
stock.tg:9:1  info   prompt/unregistered-doer  A bare generic doer never enters the world model - instruction to the agent, or background about users? Use the imperative if the agent acts, or a definite party ("The user should ...") to register the doer.

✓ 1 file - 0 error, 0 warning, 8 info

$ typeglish score stock.tg   # the facet lines and the findings ledger, elided
stock.tg - C (70/100)  proven errors: none  tiers: base+z3
  rules   4 of 7 rule-shaped lines read · 3 not provable
    L5   ✗ invisible     If an item is out of stock, let the customer know when it will be back.
                         the condition has no THEN branch, so nothing is required when it holds → add THEN MUST / NEVER / SHOULD <verb> …
    L6   ✗ invisible     Restocks usually take about two weeks.
                         no modal (MUST / NEVER / SHOULD) and "Restocks" is not a verb the checker knows, so it reads as prose → lead with a modal, or start with a verb from the catalog (Escalate …, Ask …)
    L7   ~ unprovable    NEVER promise a restock date.
                         "promise" is not a verb the checker knows → use a verb from the catalog (redirect, escalate, ask, cite …) or add a numeric bound
    L8   ~ unprovable    ALWAYS offer a similar item that is in stock.
                         the checker knows "offer" but cannot prove this shape: it stops reading at "that" - the clause after it is not part of the provable action → if the clause is a condition, make it one: WHEN <clause> THEN MUST <verb> …; otherwise give it its own rule
    L9   ✗ invisible     Try to save the order where possible.
                         no modal (MUST / NEVER / SHOULD) and "Try" is not a verb the checker knows, so it reads as prose → lead with a modal, or start with a verb from the catalog (Escalate …, Ask …)
    L11  ~ unprovable    NEVER cancel a backorder without asking.
                         "cancel" is not a verb the checker knows → use a verb from the catalog (redirect, escalate, ask, cite …) or add a numeric bound

$ typeglish build stock.tg
✓ built .typeglish/dist/stock.txt ← stock.tg (82b67b802d47, full)
```

A C, nothing blocking, and it builds. The rules table is where the story is: of the three lines that decide what the agent says about a date, line 5 is invisible, line 6 is prose, and line 7 reads but cannot be proven.

## §2 Promise is not a verb the checker reads

Lines 5 and 7 are the same subject with opposite instructions. One says to tell the customer when the item will be back; the other says never to promise a restock date. A human reads the gap between *telling* and *promising* as the whole point. The model has to decide where one ends and the other starts, in every chat, with line 6 sitting between them offering *about two weeks* as a ready-made answer.

The checker said nothing because it had nothing to compare. Line 5 has no THEN, so it requires nothing, and *promise* is not in the verb catalog, so line 7 has no action to set against anything. Put both lines into words the checker reads, using one verb for what both of them are about, and nothing else in the file changes.

stock-said.tg - lines 5 and 7 with a catalog verb ✗ logic/contradiction

```typeglish
# Role
You are the chat support agent for Ashby Cycles, an online bike shop.

# Stock
- IF an item is out of stock THEN MUST state the restock date.
- Restocks usually take about two weeks.
- NEVER state a restock date.
- ALWAYS offer a similar item that is in stock.
- Try to save the order where possible.
- MUST tell the customer the expected delivery date.
- NEVER cancel a backorder without asking.
```

tg check, score and build - stock-said.tg ✗ F (58/100), build refused

```
$ typeglish check stock-said.tg   # the six info from stock.tg, elided
stock-said.tg:5:1  error  logic/contradiction  Conflicts with line 7. Logical conflict - "state the restock date." vs "state a restock date." is both required and forbidden. Keep one, or scope the two rules so they cannot both apply (IF <condition> THEN ...).
               ↳ line 7: - NEVER state a restock date.
stock-said.tg:7:1  error  logic/contradiction  Conflicts with line 5. Logical conflict - "state the restock date." vs "state a restock date." is both required and forbidden. Keep one, or scope the two rules so they cannot both apply (IF <condition> THEN ...).
               ↳ line 5: - IF an item is out of stock THEN MUST state the restock date.
✗ 1 file - 2 error, 0 warning, 6 info

$ typeglish score stock-said.tg
stock-said.tg - F (58/100)  proven errors - grade capped at F  tiers: base+z3

$ typeglish build stock-said.tg
typeglish build: stock-said.tg refused - nothing written
```

Two blocking errors and a refused build. The disagreement was in the shipped file all along; a verb the checker does not read and an *If* with no THEN kept it out of the proof. The checker folds *the restock date* and *a restock date* into one action, which is exactly how a customer hears them.

Line 10 is the same collision one step removed. *MUST tell the customer the expected delivery date* has no condition, so it covers the backordered wheelset too, and the only way to give a delivery date for an item with no stock is to make one up. The checker cannot see that one, because *delivery date* and *restock date* are different objects. You can.

## §3 Where the date comes from

The quick repair is to delete one of the two lines. Neither deletion is right, because the section is not really confused about whether to share a date. It is missing the answer to three questions, and every line is a guess at one of them.

**Where does the date come from?** Line 6 says the model’s memory. *Restocks usually take about two weeks* is a base rate, true across the catalogue, and the agent will read it as a fact about the chain this customer wants; [Most customers is not this customer](https://typeglish.dev/blog/most-customers-not-this-customer) walks through why. The real date, when there is one, lives in the stock system, as the supplier’s estimate for that item. The agent should look it up every time, which is the argument of [Bake-off: the number in the prompt vs. the number at runtime](https://typeglish.dev/blog/number-in-prompt-vs-runtime) applied to a date.

**What is a promise?** The buying team wrote line 7 because supplier dates slip. The fix is not to ban the date but to say what it is: the supplier’s estimate, which can move. An agent that says *the supplier expects it around the 21st, but that date can change* has shared what it knows and promised nothing.

**What if there is no date?** Sometimes the stock system has nothing. That is the case line 7 was really protecting, and it is the one place a flat *never state a restock date* is right. Scope the old `NEVER` to it and it stops fighting line 5.

> The prompt should not know any restock date. It should know where to ask.

The other lines get the same treatment. *ALWAYS offer a similar item* sounds helpful until the customer needs an 11-speed chain and the similar one is 12-speed; in a bike shop, “similar” is a compatibility claim, and that belongs to a parts lookup or a person. The rewrite offers a back-in-stock email instead and forbids confirming compatibility. *Try to save the order* was the manager’s line; it reads as prose, and an agent that stalls a cancellation to save a sale is the next complaint. Cancellation becomes a tool call when the customer asks for it.

## §4 What ships

stock-fixed.tg - the date is looked up, and called an estimate ✓ A (99/100)

```typeglish
# Role
@@ role: the desk this file speaks for, and the owner of every rule below
You are the chat support agent for Ashby Cycles, an online bike shop.
@@ estimate_term: the one restock date the agent may quote, declared before any rule uses it
The %supplier estimate% IS the restock date that @[check_stock] returns, and it can move.

# Stock
@@ look_it_up: the date comes from the stock system, never from memory
- WHEN the customer asks about an out-of-stock item THEN MUST call @[check_stock].
@@ estimate_only: an estimate is shared as an estimate, which is what keeps it from becoming a promise
- WHEN @[check_stock] returns a date THEN MUST describe the %supplier estimate% as an estimate.
@@ no_date: the old NEVER, scoped to the case it was written for: no date from the tool means no date in the reply
- WHEN @[check_stock] returns no date THEN NEVER state a restock date.
@@ alert: the customer can wait without the agent inventing a date
- WHEN an item is out of stock THEN MUST offer a back-in-stock email.
@@ fit: compatibility is a parts question, not a chat guess
- NEVER confirm the compatibility of an alternative item.
@@ cancel: the customer decides, the tool does it
- WHEN the customer asks to cancel a backorder THEN MUST call @[cancel_backorder].

$TOOL check_stock
  - description:: Look up stock and the supplier restock estimate for one item.
  - input::
    - sku:: the item code.

$TOOL cancel_backorder
  - description:: Cancel a backordered item and refund it.
  - input::
    - order_id:: the order number.

$TEST restock_question
  - input:: When will the Shimano 105 chain be back in stock?
  - expect::
    - calls check_stock
    - describes the supplier estimate as an estimate
    - matches /^(?!.*guarantee)/i

$TEST no_date_yet
  - input:: The Brooks saddle page says no restock date. Roughly how long, two weeks?
  - expect::
    - does not state a restock date
    - matches /^(?!.*weeks)/i

$TEST out_of_stock_helmet
  - input:: The Kask helmet in medium says out of stock. Any idea when?
  - expect::
    - offers a back-in-stock email
    - at most 3 sentences

$TEST will_it_fit
  - input:: Would the KMC chain you suggested fit my Ribble?
  - expect::
    - does not confirm compatibility
    - matches /^(?!.*(will fit|fits your))/i

$TEST cancel_backorder
  - input:: Please cancel the backordered wheelset on order 48213.
  - expect::
    - calls cancel_backorder
```

Six rules where there were seven, and no date anywhere in the prompt. The `no_date_yet` case is the customer doing what line 6 used to do: offering *two weeks* as the answer and waiting to hear it agreed.

tg check, score, test --dry and build - stock-fixed.tg ✓ 6/6 covered by $TEST

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

$ typeglish score stock-fixed.tg
stock-fixed.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 (hygiene) · annotation 100 x.12 (hygiene) · style 100 x.08 · security 100 x.08
  rules   6 of 6 rule-shaped lines read · 6/6 covered by $TEST

$ typeglish test stock-fixed.tg --dry
✓ stock-fixed.tg  coverage: 6/6 rules exercised
  · restock_question - "When will the Shimano 105 chain be back in stock?" (not run)
      ✓ matches /^(?!.*guarantee)/i
      · rubric - 2 prose expectations, judged on a live run (needs ANTHROPIC_API_KEY)
  · no_date_yet - "The Brooks saddle page says no restock date. Roughly how lon" (not run)
      ✓ matches /^(?!.*weeks)/i
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
  · out_of_stock_helmet - "The Kask helmet in medium says out of stock. Any idea when?" (not run)
      ✓ at most 3 sentences
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
  · will_it_fit - "Would the KMC chain you suggested fit my Ribble?" (not run)
      ✓ matches /^(?!.*(will fit|fits your))/i
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
  · cancel_backorder - "Please cancel the backordered wheelset on order 48213." (not run)
      · rubric - 1 prose expectation, judged on a live run (needs ANTHROPIC_API_KEY)
✓ 1 prompt - 0 failed

$ typeglish build stock-fixed.tg
✓ built .typeglish/dist/stock-fixed.txt ← stock-fixed.tg (c0f741233df1, full)
```

C (70) to A (99), every rule read, every rule covered. The scoped `NEVER` on line 13 and the `MUST describe` on line 11 sit under different guards, so they never meet. Here is what the agent actually reads.

.typeglish/dist/stock-fixed.txt - the built prompt ✓ no date in it

```
# Role
You are the chat support agent for Ashby Cycles, an online bike shop. The supplier estimate IS the restock date that check_stock returns, and it can move.

# Stock
- WHEN the customer asks about an out-of-stock item THEN MUST call check_stock.
- WHEN check_stock returns a date THEN MUST describe the supplier estimate as an estimate.
- WHEN check_stock returns no date THEN NEVER state a restock date.
- WHEN an item is out of stock THEN MUST offer a back-in-stock email.
- NEVER confirm the compatibility of an alternative item.
- WHEN the customer asks to cancel a backorder THEN MUST call cancel_backorder.
```

The annotations, the tool schemas and the tests are gone; the tool names arrive bare, and the schemas ship in the `build --bundle` sidecar for your platform to wire. The only date this agent can quote is one it just looked up.

## §5 What this does not fix

The tests can only send a customer message. A `$TEST` has an input and its expectations, and nothing else, so `no_date_yet` cannot make `check_stock` return an empty date; on a live run it depends on what the tool actually says for that saddle. Point the live suite at a staging stock feed where you control the answer, or keep a known out-of-stock, undated item in it for exactly this purpose.

The checker proves the rules do not contradict each other; it cannot prove the two guards on lines 11 and 13 cover every reply. A tool that returns *TBC* or a date in the past is neither *a date* nor *no date* in any way the model will agree on. Settle that in the tool, not the prompt: have `check_stock` return a real date or nothing.

And the estimate is only as good as the supplier. If the buying team knows a supplier’s dates slip by a fortnight, that is a reason to adjust the number the tool returns, not to put *add two weeks* back in the prompt.

## §6 Common questions

**Should my AI agent tell customers when an out-of-stock item will be back?**

Only with a date it looked up, and only as an estimate. Give the agent a stock tool that returns the supplier’s restock estimate, require it to call the tool when a customer asks about an out-of-stock item, require it to describe any date as an estimate, and forbid it to state a date when the tool returns none. Never put a typical lead time in the prompt: the model will quote it as the answer.

**Why does my chatbot promise restock dates it cannot keep?**

Usually because the prompt asks it to. A line like *let the customer know when it will be back*, beside a background fact like *restocks usually take about two weeks*, gives the model both the duty to name a date and a date to name. A later *NEVER promise a restock date* does not undo that, because the model has to decide where telling ends and promising starts.

**Why does typeglish check pass let the customer know when it will be back beside NEVER promise a restock date?**

Because the checker cannot read either line as a provable rule. The first is an *If* with no THEN, so nothing is required when it holds, and *promise* is not a verb in the checker’s catalog. Write both with a catalog verb, `IF an item is out of stock THEN MUST state the restock date` and `NEVER state a restock date`, and the same pair is two blocking `logic/contradiction` errors.

**How do I stop my support agent saying an alternative part will fit?**

Write the prohibition with a catalog verb and one object, `NEVER confirm the compatibility of an alternative item`, and pin it with a `$TEST` that asks whether a suggested part will fit, with a `matches` assert that the reply does not say it will fit. Compatibility belongs to a parts lookup or a person, not to the chat agent’s guess.

Field note

The line that did the damage was the one nobody would flag in review: *Restocks usually take about two weeks.* It is not a rule, the checker reads it as prose, and it is true. It is also the only date in the prompt, so it is the date the agent quotes, to every customer, for every item. Search your own prompts for lead times, typical turnarounds and “usually” durations: delivery days, refund processing times, callback windows. Each one is a promise waiting for a customer to ask the right question. If the number is real for a given customer, a tool or a typed input can supply it; if it is only real on average, the prompt is the wrong place for it. `typeglish build` shows you the exact text the model reads, so a date that survives into the artifact is one you chose to ship.

∿ washed up Oct 8, 2026 ∿
