**The brief.** Below is a promotion engine specified **only in prose** — the way specs actually arrive. Your first deliverable is not code: it is a **battery of about ten assertions** — each *assertion* is one line that states an outcome you expect ("this input must produce that number") and fails loudly if the code disagrees. In other words, each assertion is one sentence of the spec written so it runs. Translate every sentence (and every collision between sentences) into one such pinned number. Only when the battery is written — and failing — do you implement.
This is the hard version of Module 1's claim that the scarce skill is specifying and verifying. Prose feels precise until you try to pin it; the two rules that read innocently interact, and the interactions are where production bugs live. Each assertion you write is the same spec, only exact enough to run — and turning prose into assertions before writing code is exactly how you will brief agents in Module 2 — TDD.
The spec — all of it, in prose (the only prose you get)
The web shop needs a basket total with promotions. PromoTotal(items, code) takes the basket's line items — name, unit price, quantity — and an optional coupon code, and returns the amount to charge:
- Volume rule. A line with 10 or more units gets 10% off that line's total.
- Basket rule. If the subtotal after line discounts is strictly over 500.00, the whole basket gets 5% off.
- Coupon rule. Code
SAVE20takes 20.00 off at the very end — and the total never goes below 0.00.
After every rule that fires, the running amount is rounded to the cent, half up, before the next rule reads it.
The rules of the game
- Battery first. One row per spec sentence, in the row's
Speccolumn write the sentence you are pinning. Aim for ~10 rows: every rule, every boundary word ("strictly", "or more", "at the very end", "never below"), and — this is where the marks are — at least two rows that pin rule interactions. Read rules 1 and 2 together slowly. Read rule 3 against an empty basket. - Watch it fail. With the stub in place your battery must be red — every check failing, because no real code backs it yet. (Checks that pass are "green"; checks that fail are "red".) A battery that cannot fail proves nothing.
- Then implement — until every row is green. No changing pinned values to match your code; the prose is the authority.
Your workbench
A hint that is not a spoiler: a basket can be over 500 gross and under 500 after rule 1. Which subtotal does rule 2 read? Your battery must know before your code does.
Battery written, engine green — or arguing with a sentence? Reveal the solution — a twelve-row battery with both interactions pinned, and the engine that satisfies it.