{
 "id": "2.12",
 "title": "Product rules",
 "department": "Product",
 "department_slug": "product",
 "direction": null,
 "branded": false,
 "status": "draft",
 "owner": "Param",
 "last_verified": "Mon Oct 26",
 "holds": "Truth first, read only, one version, claims need proof, every brand, Sample labels",
 "urls": {
  "html": "https://handbook.joinsquareup.com/product/product-rules",
  "markdown": "https://handbook.joinsquareup.com/product/product-rules.md",
  "json": "https://handbook.joinsquareup.com/product/product-rules.json"
 },
 "other_directions": [],
 "tldr": {
  "headline": "Twenty four rules every feature must follow, or it does not ship",
  "points": [
   {
    "icon": "flag",
    "text": "Truth first: no invented numbers, quotes, reviews or backstory, and errors never read as zero."
   },
   {
    "icon": "lock",
    "text": "Read only in v1; nothing dummy or test reaches production."
   },
   {
    "icon": "check",
    "text": "Every fix works for every brand, platform and card, and heals saved data."
   },
   {
    "icon": "heart",
    "text": "One version then Redo it, no disclaimers on ads, sell relief never discounts."
   },
   {
    "icon": "warn",
    "text": "Never disconnect Arata's Meta or Shopify; code guards it."
   }
  ],
  "stat": {
   "value": "24",
   "label": "product rules"
  },
  "decide": "Is the 25 Oct Pro sheet exception still right? Proposal: drop it at the redesign.",
  "mood": "solid"
 },
 "sources": [
  "brew origin/main b91e364: SPEC.md:11-20, CLAUDE.md:7-45, DUMMY.md:25-30, SCOPE.md:36-38",
  "brew origin/main: card-plan.js:36, claims.js:219, rival-ad.js:7, connectors/index.js:267, docs/handover/product/04-content-and-accuracy-rules.md",
  "brand-directions/_shared/product-model.md:97, 162-207",
  "brand-directions/docs2/content/decisions.mjs:3-23",
  "brand-directions/BRIEF.md section 1",
  "memory: feed-for-all-brands, fix-as-product, brew-one-version, brew-proof-plain-make, prod-clean-only, never-disconnect-arata-meta, brew-quiet-ui, no-disclaimers-in-ads, sell-relief-not-discounts, keep-all-moves, brew-access-rules, brew-qa-round2-2026-10-24, brew-card-asset-match, brew-rival-pictures, harry-reviews-fictional"
 ],
 "open_questions": [
  "**AGENTS.md lets the handbook name the company behind our team, WRITING.md forbids it.** Proposal: follow WRITING.md and say our team, and fix AGENTS.md.",
  "**Is the 25 Oct Pro sheet exception still right?** Proposal: drop it at the redesign."
 ],
 "parts": {
  "Answer": "These are the rules every Brew feature must follow, each with where it is set and how it is enforced; a change that breaks one does not ship.",
  "Today": "| # | Rule | Where it holds | Source |\n|---|---|---|---|\n| 1 | Truth first: no invented numbers, quotes, founders, reviews or backstory; unbacked numbers say to confirm | Prompts, `stat-check.js`, `test/honesty.test.js` | [src: SPEC.md:13] [src: DUMMY.md:30] |\n| 2 | Observed, inferred and implication stay separate; never state a rival's motive | Prompts | [src: SPEC.md:14-15] |\n| 3 | An error is never shown as none or 0 | Readers keep `error` | [src: CLAUDE.md:12] |\n| 4 | Read only: nothing posts, sends to customers, pauses or moves budget in v1 | Read only scopes | [src: SCOPE.md:36-38] [src: brand-directions/docs2/content/decisions.mjs:22] |\n| 5 | One version, then Redo it; never three options | `MAKE_N` all 1 | [src: card-plan.js:36] [src: memory brew-one-version] |\n| 6 | Claims need proof: a health or measured claim needs the store's study or an approved claim | `checkCopy` on every surface | [src: claims.js:219] [src: memory brew-qa-round2-2026-10-24] |\n| 7 | A Play is never evidence; proof must prove the claim | `evidence.js`, `proof-logic.js` | [src: memory brew-proof-plain-make] |\n| 8 | Every fix works for every brand, platform and card, and heals saved data | `test/non-shopify.test.js`, audits | [src: CLAUDE.md:20-40] [src: memory feed-for-all-brands] [src: memory fix-as-product] |\n| 9 | Simulated things carry a Dummy tag, a code comment and a DUMMY.md row | `public/dummy.css` | [src: DUMMY.md:3-10] |\n| 10 | Nothing dummy or test reaches production, except the Pro sheet, the Marketplaces label and the catalog photo fallback | `db/prod-clean.mjs` clean gate | [src: memory prod-clean-only] |\n| 11 | Never use a rival's picture as ours; Make our version gets only a written breakdown | `rival-ad.js`, `isRivalCard` | [src: rival-ad.js:7] [src: memory brew-rival-pictures] |\n| 12 | The card's picture shows what its words promise | `cardProduct`, `cardScene` | [src: memory brew-card-asset-match] |\n| 13 | No disclaimers or AI labels on ad creative | Prompts | [src: SPEC.md:18] [src: memory no-disclaimers-in-ads] |\n| 14 | Plain, one glance language; quiet pages with no zero tiles | `plain.js`, quiet rules | [src: SPEC.md:19] [src: memory brew-quiet-ui] |\n| 15 | Sell relief, never discounts, in badges and nudges | Copy | [src: docs/handover/product/04-content-and-accuracy-rules.md:24] [src: memory sell-relief-not-discounts] |\n| 16 | They or them for anyone whose pronouns are unknown | Prompts | [src: SPEC.md:20] |\n| 17 | Cost cuts never drop Plays; make each cheaper | Build | [src: memory keep-all-moves] |\n| 18 | Brand data is the brand's: only its own email, an invite or staff open it | `auth.js`, `closed-gate.js` | [src: memory brew-access-rules] |\n| 19 | Connected numbers stay members only and beat the site read while fresh | `facts-desk.js` | [src: memory brew-connected-facts] |\n| 20 | Never disconnect Arata's Meta or Shopify | `PROTECTED_CONNECTIONS` | [src: connectors/index.js:267] [src: memory never-disconnect-arata-meta] |\n| 21 | Say Plays, never moves, wherever a person reads | `brew-name.js`, app labels | [src: brand-directions/docs2/content/decisions.mjs:4] |\n| 22 | No fake reviews or testimonials, ever | Review styles quote real reviews word for word | [src: memory harry-reviews-fictional] [src: memory brew-jam-v2] |\n| 23 | Sample labels on every invented example in docs and design | Docs check | [src: brand-directions/BRIEF.md section 1] |\n| 24 | Never show vendor or model names to a founder; a price only on the confirm sheet | Redesign rule | [src: brand-directions/_shared/product-model.md:97] |",
  "Tomorrow": "| Rule | Version | Tag |\n|---|---|---|\n| The glance rule: closed card of five parts, 25 words at most | v1 | New [src: brand-directions/_shared/product-model.md:166-178] |\n| One of each thing: one sheet, one toast, one empty state, one way into each thing | v1 | New |\n| Every post or schedule waits for a yes, with undo | v2 | New |\n| Results always show their method and source | v3 | New |\n| Nothing runs outside rules the founder set | v4 | New |",
  "How we do it": "1. Before shipping, check the change against this table.\n2. For a new class of break, add a test or audit and a heal.\n3. Run the suite and the relevant audit:\n   ```\n   AI_MOCK=1 node --test test/*.test.js\n   node tools/audit-card-fit.mjs DIR\n   ```\n4. A rule changes only by Param's call, logged in the decisions log.",
  "Numbers": "| Metric | Definition | Where measured | Status |\n|---|---|---|---|\n| Rule breaks found | Findings per QA round that break a rule here | QA reports | Proposed |\n| Clean gate refusals | Promotions refused by the clean gate | `tools/promote.sh` output | Proposed |",
  "Open": "1. **AGENTS.md lets the handbook name the company behind our team, WRITING.md forbids it.** Proposal: follow WRITING.md and say our team, and fix AGENTS.md.\n2. **Is the 25 Oct Pro sheet exception still right?** Proposal: drop it at the redesign."
 }
}