# Reader brief — make the honest checkout state a tested feature **Use this if:** you are building a shop before the payment path is live, or you suspect some copy on your store is describing a state the product is no longer in. **Time:** half a day. **You need:** the storefront source, the settings/config that decides whether payments are on, and a browser you can drive. This is the method behind *"Checkout is not live yet"*: the disabled button is not a placeholder, it is a claim with a test. The pack has the copy map — which words live where and which fields are traps — and the honest-states inventory that turns each state into an assertion. ## The prompt ```text You are auditing the payment copy of a storefront. The goal is not better copy. The goal is copy that is TRUE in every state the product can be in, and a test that fails when it is not. INPUTS - The storefront source and templates. - The configuration that controls whether payments are enabled (keys, flags, env). - The live or local rendered pages for each state you can produce. - Any copy that lives in a CMS, vault or settings store rather than in code. DO 1. Enumerate the product states that change what a customer can do. At minimum: no payment keys, payment keys in test mode, payment keys live, payment unavailable. Add any state the code has. 2. For each state, write the exact strings the customer must see: button label, disabled/ aria-disabled, the reason line, the cart toast, the meta description, any preview banner. 3. Find every claim in the rendered product and map it to the state it describes. Flag any string that is latched to a COMMENT or a past state rather than to the state it is rendered in. 4. Verify in the DOM, not the source: button text, the disabled property, aria-disabled, the reason line's presence and visibility, the meta description, and the contrast of the disabled line. Each is an assertion with a pass/fail. 5. Prove go-live is a configuration change: with keys absent the button is disabled and says why; with keys present the real checkout path is used. No code edit and no deploy may be able to flip the claim by accident. 6. Audit the copy that lives in data: a field that is stored but rendered nowhere is a trap; a field missing from the server's length-cap table is a silent truncation. Record both. 7. If any page is a design preview or a test surface, make it say so in its meta description and its first paragraph. ACCEPTANCE CHECKS - The disabled state is genuinely unusable and announced as unusable. - The reason is present and readable, with measured contrast. - No page claims payment is live when the configuration says it is not, and none claims it is disabled when it is enabled. - The preview/review surface explicitly says it is not the live shop and makes no network calls. - A field edited in the CMS reaches the page the operator expects, or the contract says it does not. DELIVERABLE A state register (state -> exact copy -> assertion), the DOM assertions, a list of false or unowned claims found, and the configuration change that is the only way to go live. ``` ## Feed it these files | File | What it gives you | |---|---| | `copy-map.md` | the surface map: which words live in code, which in the vault, and the traps | | `honest-states.md` | the state inventory and the assertions already written for the shop | ## What good looks like - [ ] The button's text is exactly the state's sentence, and `disabled` + `aria-disabled="true"` are both set. - [ ] The reason line is present, visible, and passes contrast — not a tooltip or a greyed-out note. - [ ] The cart toast and the meta description carry the same truth as the button. - [ ] A state change is a config/vault write, not an edit to a template. - [ ] The design preview says "not the live shop" and makes no network requests. - [ ] Every string that claims a capability is owned by the state that enables it. ## Failure modes this piece paid for - **Copy latched to a comment, not a state.** The live shop accepted real payments and seventeen occurrences across five files still said "checkout is not live yet". They were true when written; then the keys were configured and the copy did not move. A string that is not derived from state is a claim waiting to go stale. - **A field stored but rendered nowhere.** The Identity card's meta-description field was saved by the desk and appeared on no page; the real meta description came from the SEO card. Two fields with the same name and different powers is a trap. A copy contract must say which one renders. - **A field missing from the server cap table.** A long footer line was silently dropped on save until the cap table was fixed. Truncation is a copy bug that looks like a design bug. - **A true-today claim that is not derived.** "Nothing can be ordered yet" was true before Stripe and false after. If the sentence is not derived from the configuration, the day it becomes false is invisible. - **A preview that pretends.** The design-review page must say it is a preview in the meta description and the first paragraph. ## Where to go next in the pack Read `copy-map.md` §3 for the three change paths (code, vault, per-product) and §4 for the resolved false-copy incident — it is the best worked example. Then `honest-states.md` for the assertions. The rule to carry: **customer-facing state copy is not latched to a comment, it is latched to the state it describes.**