--- name: honest-metrics-audit description: Check that every number your UI shows actually means what its label claims, by tracing each displayed figure back to the query that produced it. Catches counts of the wrong entity, stale denominators, placeholder traction, and labels that quietly overstate. Use before a launch, a pricing page, or any screen that shows social proof. --- # Honest Metrics Audit ## Install Save this file as `~/.claude/skills/honest-metrics-audit/SKILL.md`, or `.claude/skills/honest-metrics-audit/SKILL.md` to scope it to one repo. Claude Code auto-discovers it. Invoke with `/honest-metrics-audit` or by asking "do the numbers on this page actually mean what they say?". ## Why this exists Nobody sets out to publish a false number. It happens because a label and a query drift apart. Someone computes `items.filter(i => i.seller.verified).length`, which is a count of ITEMS. Someone else renders it under the label "Verified sellers". Both lines are individually reasonable. Together they tell every visitor there are fifteen verified sellers when there is one. No test fails, because no test knows what the label says. This is worse than an ordinary bug in one specific way: it is indistinguishable from lying. A visitor who discovers it does not conclude you made a mistake. And for anything that looks like traction (users, downloads, revenue, reviews) an overstated number is the single fastest way to lose the trust you were trying to build with it. ## Step 1: Inventory every displayed number Find the components that render figures: ``` rg -n "toLocaleString|formatCount|formatStat|Intl\.NumberFormat|CountUp|\.length\}" \ --type-add 'ui:*.{tsx,jsx,vue,svelte}' -t ui ``` Also find the labels themselves, which is often faster: ``` rg -n "(users|customers|sellers|buyers|members|downloads|installs|reviews|ratings|sales|revenue|active|verified|trusted)" \ -i --type-add 'ui:*.{tsx,jsx,vue,svelte}' -t ui ``` Build a table. One row per number a real visitor can see: | Screen | Label shown | Expression | File:line | | --- | --- | --- | --- | Do not skip numbers that seem obviously fine. The mislabeled ones always seem obviously fine. ## Step 2: For each row, name the unit This is the whole audit. For every number, answer in one sentence: **what is one of the things being counted?** Then compare that answer to the noun in the label. Mismatches to look for: - **Wrong entity.** Counting items but labelling people. Counting rows but labelling distinct users. Counting events but labelling sessions. - **Missing distinct.** `orders.length` labelled "customers" when one customer can order twice. - **Wrong population.** A count that includes test accounts, internal staff, soft-deleted rows, or your own first-party listings, under a label implying third parties. - **Wrong window.** "Active users" computed with no time bound. "This month" computed from a rolling 30 days. "Today" computed in the wrong timezone. - **Wrong denominator.** A percentage whose base excludes the cases most likely to fail, which flatters the rate. Write the corrected label OR the corrected expression for every mismatch. Both are valid fixes; choose whichever makes the number more useful. ## Step 3: Hunt fabricated and placeholder figures ``` rg -n "(stars|downloads|users|reviews|rating|count)\s*[:=]\s*[0-9]{2,}" -t code rg -n "\b(1,?234|4\.[89]|99\.9|10,?000\+|trusted by|join [0-9])" -i -t code ``` Flag any number that is a literal rather than a query result, anywhere it can reach a user. Then trace whether it can: - Is it in a seed or fixture file that a production command could run? - Is it a fallback value used when the real query fails? - Is it a default prop that renders when data is missing? A hardcoded `4.9` rating with no reviews behind it is the most damaging thing in this category, and it usually arrives as design placeholder text that nobody removed. ## Step 4: Check the zero and failure paths Two questions per number: **What renders when the true value is zero?** A brand-new product showing "0 downloads" is honest but reads as dead. Showing nothing is also honest. What is not acceptable is a fallback that substitutes a non-zero placeholder. Find the zero handling and say which of the three it does. **What renders when the query fails?** Trace the error path. If a failed lookup falls back to a cached, default, or hardcoded figure, the UI will assert a number that is not merely stale but unsupported. A stat that fails closed (hidden) is correct. A stat that fails to a plausible-looking default is a defect. ``` rg -n "\?\?\s*[0-9]+|\|\|\s*[0-9]+|catch.*return\s*[0-9]+" -t code ``` ## Step 5: Check aggregate claims in prose Numbers hide in sentences, not just in stat blocks: ``` rg -n "(over|more than|nearly|join|trusted by|used by|thousands|millions)" \ -i --type-add 'ui:*.{tsx,jsx,vue,svelte,md,mdx}' -t ui ``` Marketing copy is rarely wired to a query at all. For each claim, find the evidence or mark it unsupported. "Trusted by thousands of developers" in a hardcoded string is a claim your code cannot back. ## Step 6: Report ``` [SEVERITY]