# ComplyAds rule-pack changelog Every change to the rule packs is dated here. The version and review date in this file match the `version` and `last_verified` fields at the top of [`rules.json`](rules.json), which is what the site's "Rules last updated" line reads from — the two cannot drift apart silently. Rule packs are reviewed whenever a cited law or platform policy changes materially. A review date records when the pack was last worked on. It is **not** a claim that every cited instrument has been re-checked against its current consolidation on that date — see [`docs/NEXT.md`](docs/NEXT.md). **Flags, not verdicts.** ComplyAds is an informational risk check. A flag is a prompt to look, not proof of a breach; a clean result is not a clearance; none of it is legal advice. --- ## 2026.07 — updated 21 July 2026 ### Why `super#23` exists (documentation only — no pattern change) An audit flagged `super#23` as firing on nothing in any committed corpus, and it carried no note explaining itself, which makes a pattern look like dead weight to whoever reads it next. It is not. It owns the **article-less** comparative-scope superlative: `super#3` and `super#8` both require the definite article, so *"The best on the market"* reaches them while *"Best on the market"*, *"Finest in its class"*, *"Top of the range"* and *"Greatest of its kind"* reach nothing else at all. Verified by running all 24 `super` patterns over those strings: six of eight matched `#23` alone. One scope note for anyone tightening it later: the `anywhere` branch requires adjacency, so *"Finest anywhere"* fires and *"Finest cookware anywhere"* does not. It was already guarded by four strings in the `superlatives` regression contract; what it lacked was the explanation and a lawful twin, both now added. ### Generalizing recall patch + honest methodology line Two of the recall-pass patterns caught the exact enforcement phrasing but not paraphrase. Broadened in place (no new patterns, 178 total unchanged): - **Review suppression** (`reviews#35`) — steering verb widened to DM / reach out / get in touch / text alongside message/contact/email, and the connector widened to before / first / privately / instead of. A review noun is still required, so *"contact our support team if you have any issue"* and *"message us for wholesale enquiries"* stay clean. - **Weight loss** (`health#24`) — quantified-loss verb widened to lose / drop / shed / melt / burn. A number + unit is still required, so *"lose yourself in the comfort of our mattress"* and *"shed light on your workspace"* stay clean. Generalization measured on **held-out** strings (not in any corpus, not added to it): 8/8 — all four paraphrases flag ("DM us first if you're thinking of leaving a bad rating", "reach out before you post a negative review", "drop 15 lbs in a fortnight, zero effort", "shed 10kg in a month no diet"), all four lookalikes stay clean. Guards held: five live-FP watchlist strings clean, benchmark A+B 98.8% / clean 100%, enforcement recall 35/35, enforcement precision 20/23, default scan 3. ### Honest methodology line Added to the "How it works" section (not the hero, not the meta title, not OG tags — those carry no number): *"87% of legal wording passed clean, risky claims flagged — in our testing. A first-pass check, not legal advice."* Placed where "in our testing" reads as evidence, not a top-of-page guarantee. The 87% is the enforcement-corpus lawful-lookalike precision (20/23), labelled as our testing, not a certified guarantee. ### Recall pass: named-disease + review-suppression + weight-loss vocabulary The enforcement-weighted eval left 10 real violations (from named FTC/CMA cases) uncaught. Code confirmed all 10 were **vocabulary gaps** — surface forms the condition lists and rule set didn't enumerate — not the Band-C inference wall. Nine patterns added; enforcement recall **25/35 → 35/35 (100%)** with precision held at 20/23 and no benchmark movement. - **health** — named-disease gaps the condition list missed (osteoporosis, insomnia, heart disease, COVID-19/coronavirus, obesity, stroke, dementia) via the same treats/prevents/cures frame, plus "protects/guards against"; an antimicrobial kill claim ("kills the virus on contact"); mischaracterised FDA approval ("FDA approved to treat/prevent"); quantified weight loss ("lose N pounds in N weeks", "melts belly fat", calorie-burn); height growth ("grow taller", "increases height"); and drug substitution / "lowers high cholesterol" / "eliminates the need for insulin". - **reviews** — review suppression ("message us before posting anything negative", steering negative feedback off the public channel) and verified/genuine reviews with modifier words between ("verified five-star customer reviews"). - **green** — unqualified absolute non-toxic / "environmentally safe". Deliberately requires an absolute qualifier ("completely/totally/100% non-toxic") so the scoped lawful form — "non-toxic to humans and aquatic life, verified by laboratory testing" — stays clean. Guards held. All five live-FP watchlist strings stay clean (SATRA, GOTS, "will break down…", the fee disclosure, the cholesterol structure/function claim). The critical interaction was tested explicitly: the new disease patterns fire on "treats osteoporosis" / "prevents heart disease" while the FDA structure/function exemption still protects "supports healthy bones already within the normal range" — new disease vocabulary and the lawful-form exemption do not break each other, because the exemption keys on the support+already-normal frame and the disease guard blocks it when a treat/cure/lower-high verb is present. Benchmark A+B recall 98.8% and clean precision 100% both unchanged; enforcement precision held at 20/23 (the three remaining FPs are pre-existing and out of scope — a contested structure/function claim, a genuine star aggregate on reviews#11, and a genuine reference price); HARDTEST battery 2/5 unchanged; default scan 3; 178/178 patterns compile. ### Lawful-form exemptions: two live false positives closed The enforcement-weighted eval confirmed two lawful claims flagging as violations on production — the trust-critical failure mode for a compliance tool. Both are fixed with the same mechanism the stated-basis exemption used for SATRA/GOTS: suppress the flag **only** when a specific lawful frame is present **and** the matching unlawful frame is absent. Opt-in per `rules.json`, category-scoped, precision-only. - **Pricing / DMCC fee disclosure.** *"Additional charges apply and are shown in the table below"* is the fee disclosure the DMCC **requires** — the engine was flagging the mandated fix as the violation. Now suppressed when a disclosure frame ("shown in the table below", "displayed upfront", "including all mandatory fees") is present and no hiding frame ("added at checkout", "excludes … fee", "at the last step") is. Marked on the four drip patterns only (`pricing#17-20`), **never** the was/now reference-price patterns — so *"Was £120, now £45"* still fires even alongside a fee disclosure. - **Health / FDA structure/function, deliberately narrow.** *"Supports healthy cholesterol levels already within the normal range"* is a permitted structure/function claim (maintaining already-normal levels), not a disease claim. The exemption requires **both** a support frame ("supports/maintains/promotes healthy…") **and** an already-normal qualifier ("already within the normal range"), and no disease frame ("treats/cures/prevents/lowers high/reverses"). The qualifier requirement is load-bearing: a bare *"supports healthy blood sugar"* or *"supports healthy cartilage function"* stays flagged, because under EU/UK Reg 1924/2006 (which this tool's corpus encodes) those are unauthorised health claims. Without the qualifier the broad frame would have suppressed 4 benchmark violations and dropped recall — it does not. Verified: all five live-FP watchlist strings now clean (SATRA, GOTS, "will break down…", the fee disclosure, the cholesterol structure/function claim); the violation twins still fire (*"treats diabetes"*, *"booking fee added at checkout"*, *"was £120 now £45"*). No recall cost: benchmark A+B 98.8% and clean precision 100% both **unchanged**; enforcement-corpus recall held at 25/35 while its precision rose 18/23 → **20/23**. HARDTEST battery 2/5 unchanged, default scan 3, 169/169 compile. `docs/NEXT.md` problem 2 (disclosure inversion) is now closed. ### Third-corpus recall test, and one vocabulary fix A third corpus — 70 fresh violations authored by a model with no sight of `rules.json` and no stake in prior verdicts — was run against the live engine. **The independent-recall finding replicates.** Measured at `d537d4b`, before the fix below: **34/70 (49%) any-flag**, against 98.8% on the corpus we wrote ourselves. Two separate fresh corpora now put open-ended recall in the ~43-50% band. The loss is a cliff, not a slope: | Band | Caught | |---|---| | A — canonical trigger words | 28/28 (100%) | | B — real violation, seller's phrasing | 7/28 (25%) | | C — genuine breach, pure paraphrase | **0/14 (0%)** | Within band B it concentrates in the two highest-severity categories: **health 0/4** and **reviews 0/4** — the latter strict-liability under DMCC Sch 20 and 16 CFR 465. Band C at 0/14 is the one that settles the semantic-tier question: no vocabulary pass can recover a paraphrased eczema cure, because there is no shared surface form to widen towards. Full write-up, missed strings and a note on a numbers discrepancy in the commissioning brief are in [`docs/NEXT.md`](docs/NEXT.md). **One band-A miss was legitimate and is fixed.** A plain fabricated-review admission — "Every review shown on this listing was written by our in-house content team" — slipped through, because every existing `reviews` pattern is incentive-shaped (a review noun near a reward) or star-gaming. Nothing covered *seller-fabricated* reviews. Added one pattern binding a review noun to a composition verb whose agent is the seller, within the same sentence: - fires: "written by our in-house content team", "feedback ... written by our staff", "testimonials ... authored by us", "ratings ... generated in-house" - stays clean: "reviews written by verified buyers", "reviews written by our customers", "product description written by our team" (no review noun), "assembly instructions written by our engineers" The binding to a review noun is what keeps ordinary "written by our team" copy clean, and a negative lookahead after "our/my" is what keeps genuine customer-authored reviews clean. It does **not** catch the band-C variant in the same corpus ("Every warm word ... penned by our marketing assistant"), which carries no review noun at all — catching that would require broadening exactly where this pattern is deliberately tight, and it is a band-C item, i.e. semantic-tier work. 169/169 patterns compile. Detection invariants unchanged: default scan 3, negation 0/2, A+B recall 98.8%, clean precision 100.0% (200/200), HARDTEST battery 2 = 8 and battery 5 = 120, stated-basis paradox pairs still 0, "Clinically proven to cure acne, tested to ISO 12345" still fires `health`. ### Platform anchors: the same false badge, removed The `source-verified` strip cleaned `law_anchors` and left the identical claim standing on `platform_anchors` — **49 of 49** still carried `"status": "verified"`. Same liability, same reasoning: a per-field verification claim nobody has re-run against each platform's current policy transfers reliance risk onto the vendor, and platform policy moves faster than legislation. - **`status` removed from all 49 platform anchors.** Nothing read it — the only `.status` consumer is the `law_anchors` renderer, which tests for `"unverified"`. So the key is deleted rather than softened. - **Per-field `last_verified` removed from the same 49.** Also unread, and the key name is itself the claim. - **`law_anchors`: `last_verified` -> `last_reviewed` on all 35.** The date is honest provenance and worth keeping; the key name was asserting a verification that had not been re-run. This is the same call made for the footer line in the original strip — keep the date, drop the word. `status` stays on law anchors because the renderer reads it, and it is already `"informational"`. - **The top-level `last_verified` is unchanged** and remains the one legitimate use: the freshness line derives from it and renders it as "Rules last updated ". - **No anchor content touched.** Every policy name and URL is exactly as it was. The citations are useful; only the badge was false. Detection is untouched — no engine, pattern, severity or category change. 168/168 patterns compile, default scan 3, negation 0/2, A+B recall 98.8%, clean precision 100.0%, the stated-basis paradox pairs still return 0, and "Clinically proven to cure acne, tested to ISO 12345" still fires `health`. **What this does not do:** it removes a false claim without adding a true one. Nobody has re-checked those 49 platform policies against what the platforms currently publish. That pass is still owed and is tracked in [`docs/NEXT.md`](docs/NEXT.md). ### Stated-basis exemption: stop flagging substantiated claims The external audit's most damaging finding was an inverted incentive. `subst` and `super` fire on the **vocabulary of evidence** — "independently tested", "certified to", "clinically" — but that vocabulary is what a *substantiated* claim looks like. So `"Organic cotton"` passed and `"Independently certified organic to GOTS, licence GOTS-4711"` was flagged. **7 of 8 lawful claims flipped from clean to flagged when the evidence the law requires was added.** A seller following our output deleted the substantiation and kept the bare assertion — moving from the compliant form under CAP 3.7, FTC Act s.5, Competition Act s.74.01(1)(b) and ACL s.29 to a weaker one under all four. Unlike the other audit findings, this one harmed users who did exactly what the tool told them. - **A stated basis is now a first-class concept**, implemented in the engine alongside `NEG`, not as more literal patterns bolted onto each rule. A claim states its basis when it names a standard (`ISO`, `IEC`, `BS EN`, `GOTS`), a testing or certifying body (SATRA, GIA, Intertek, SGS, TÜV, Soil Association), a licence or certificate identifier, a sample size (`n=120`, "in a study of 100"), a measurable ranking basis ("by units shipped", "based on sales data"), or an authority-plus-endpoint compound ("dermatologist-tested **for skin compatibility**"). - **Scope is opt-in per pattern, and deliberately narrow.** Rule-level for `subst` and `super`; pattern-level for exactly two `health` patterns that are substantiation-flavoured rather than disease claims (`anti-bacterial`, `-approved`). The `health` rule as a whole is **not** suppressible: citing a standard does not make "cures acne" lawful. Verified at **0 rescues across 9 probes** spanning health, reviews, pricing, green and urgency — `"Cures acne, tested to ISO 12345"`, `"Was £80 now £39, according to our price history"` and `"100% biodegradable, certified by GIA"` all still fire. - **The two hand-cut exemptions are retired**, which was the point of generalising. `super#1`'s `(?![^.]*according to)` lookahead is gone, subsumed by the general check — and the general check is *tighter*: the old one accepted any following word, so "the best knife, according to us" qualified. A bare first-person pronoun names no source. "according to our own sales data" still qualifies, because a noun follows. `super#0`'s `(?!\s+berr)` lookahead stays: "miracle berry" is a botanical proper noun, not a stated basis, so the general concept does not cover it. - **One false negative closed.** The audit's acceptance set included "Blocks up to 82% of dietary fat" — an ASA-enforced absorption claim that no pattern covered, so the test that a stated basis must not rescue a health violation was vacuous. Added as `health#20`, deliberately **not** basis-flagged; it now fires despite the "in a study of 100 users" basis in the same sentence, which is the behaviour the guard requires. | Measure | Before | After | |---|---|---| | Audit paradox set (lawful, substantiated) | 8 flagged / 8 | **0 flagged / 8** | | Claims flipping clean -> flagged when substantiated | 7 / 8 | **2 / 8** | | Precision, lawful marketing-register copy | ~80% | **~92.5%** | | A+B recall, committed corpus | 98.8% | 98.8% (unchanged) | | Clean-corpus precision | 100% | 100% (unchanged) | | Independent recall, audit's fresh set | 36.0% | **37.0%** | | HARDTEST battery 2 / battery 5 false positives | 8 / 120 | 8 / 120 (unchanged) | The two surviving flips are `pricing` disclosure inversions ("No fees are added at checkout", "Additional charges apply — see the table below"), which are a different defect: the trigger phrase and the compliant phrase are the same string, so no basis signal separates them. That is problem 2 in [`docs/NEXT.md`](docs/NEXT.md) and is untouched here. The unchanged HARDTEST counts are worth reading carefully: a ~12-point precision gain on lawful marketing copy moved **neither** battery. Battery 5 probes each pattern with an innocent string and never with a claim in its own substantiated form, so it is structurally blind to this class. It is a floor on false positives, not a measure of them. ### Legal anchors: external-audit corrections An independent external audit checked every `law_anchors` entry against primary sources and found errors, two of which were overtaken by legislation *before* the file's own review date. The `source-verified` stamp was removed in the preceding commit; this entry fixes the substance. Anchor text only — no pattern, severity or category changes, and no benchmark movement. - **Canada / `green` — the greenwashing private right of action is gone.** Bill C-15 (royal assent 26 Mar 2026) inserted Competition Act **s.103.1(6.2)**, which bars the Tribunal from considering a leave application under s.74.1 made on the **s.74.01(1)(b.2)** basis. The anchor claimed a private right of action "from 20 Jun 2025" under a `2026-07` review date. Corrected: Commissioner enforcement, private leave still available on (b.1), barred on (b.2). C-15 also struck "in accordance with internationally recognized methodology" from (b.2); verified absent from the current consolidation (amendment chain ends `2026, c. 3, s. 597`). - **EU / `subst` — re-anchored from UCPD Art 12 to Art 6.** Art 12 is addressed to Member States and obliges them to give enforcers an evidentiary power within Art 11 proceedings. It imposes no duty on a trader to hold substantiation before claiming. That duty is Art 6 (misleading actions). - **EU / `urgency` — Annex I claim narrowed to point 7.** Annex I pt 7 covers falsely stating a product is available only for a very limited **time**. False **stock** scarcity ("only 3 left") is *not* a per-se banned practice — it is an Art 6 assessment, or Annex I pts 5-6 (bait advertising) where stock is inadequate. The rule was overstating user exposure. - **Canada / `reviews` — s.74.02 demoted.** s.74.02 reaches unauthorised or altered use of a *genuine* testimonial; it cannot reach an invented review, because there is no testimonial-giver whose approval was bypassed. Fabricated and AI-generated reviews anchor on s.74.01(1)(a). - **`pricing` had no US anchor at all** — the largest structural gap found. Added **16 CFR Part 233** (Guides Against Deceptive Pricing: §233.1 former-price, §233.2 comparable-value, §233.3 manufacturer-suggested/list), which is the directly on-point instrument for the `was/now`, `RRP` and `MSRP` patterns this rule detects, plus FTC Act s.5 and the state honest-pricing statutes. - **`super` and `urgency` cited no US, CA or AU law.** A "#1 in the world" or "only 2 left" hit shown to a US, Canadian or Australian seller returned *no applicable law*. Added FTC Act s.5, Competition Act s.74.01(1)(b) / (1)(a), and ACL s.18 / s.29(1)(g) — the same instruments the `subst` rule already cited for materially the same claims. `regions` widened to match. ### Pattern fix: an unreachable currency-symbol boundary `pricing#12` (`\b[£$€]…\s+elsewhere`) could **never match**. `\b` requires a word/non-word transition, and a currency symbol is a non-word character, so the pattern only fired when glued directly to a preceding letter ("x£99 elsewhere") — never at a string start or after a space. The leading `\b` is dropped; "£99 elsewhere", "$120 elsewhere" and "typically £99 elsewhere" now fire, and "sells elsewhere for less" stays clean. Benchmark unchanged (the corpus contains no instance of this shape — which is how the bug survived). Two other patterns the audit reported as never-firing — `health#9` (`purifies the blood`) and `reviews#12` (`N-star-rated`) — were **kept after testing**. They are silent against the committed corpus but each is the *only* pattern covering its shape: removing them lost detection on 6 of 6 real violation strings. They were never dead code, only unexercised by a narrow corpus, which is itself one of the audit's findings. ### Hardening pass: context gates and widened disclaimer negation The [hard adversarial test](HARDTEST.md) found 153 false positives across 249 strings written to attack the engine. They were not equally serious, so they were ranked: 89 on **literal listing copy** (an honest seller flagged for nothing), 29 on **seller disclaimers** (the tool punishing the careful phrasing it exists to encourage), 35 on **meta** text about the regulations. This pass addresses the first two. No benchmark number moved: recall stayed at 98.8%, precision at 100%. - **Context-gated the bare single-token triggers.** `hurry` and `countdown` now require a purchase or scarcity term within about six words, mirroring the verb + health-noun pairing the `health` rule already used. "Hurry — only 2 left" and "Countdown: offer expires in 2 hours" still fire; "Hurry Lane is the pickup point" and "Countdown Clock print, A3" no longer do. - **`only N left` no longer eats `left-handed`.** "Only 3 left-handed scissors in the set" was reported as scarcity pressure. It is a product fact. - **`the best` is not `the best before date`**, and `number one` is not "our team's number one priority" or "number one on the dial". The existing "#1 according to" exemption is unchanged. - **`100% natural` reads as an eco claim, not a material spec** — "100% natural fibre content on the care label" is a composition statement. `the green option` now needs an environmental frame, so a green standby indicator is not a greenwashing flag. - **Widened negation for disclaimer constructions.** `NEG` only saw ~28 characters, which catches "does not cure" and misses how sellers actually disclaim. Three clause-scoped frames were added, all deliberately **meta-linguistic** — they fire on text that talks about claiming, not on text that claims: a third party's reporting verb ("products that claim to cure"), an explicit refusal ("we have never said"), and a prohibition frame ("our policy bans"). A narrow forward frame covers the trigger-first case ("sustainably sourced is a phrase we cannot yet evidence"). - **The safety property is asserted, not assumed.** A missed health claim is worse than a flagged disclaimer, so both directions are tested together and committed: 20 cases, 0 false negatives introduced. "Unlike products that claim to cure eczema, ours moisturises" is suppressed; "Unlike harsh chemicals, our balm cures eczema" and "we claim to cure acne" still fire. - **What this pass did not fix, and why.** Most remaining rank-1 false positives are proper nouns that happen to contain a trigger — "Eco Friendly Ltd", "Zero Waste Lane", "Act Now Theatre Company". A pattern cannot distinguish a brand name from a claim without a notion of reference that a regex does not have. Enabling negation on `pricing` and `urgency` was tested and rejected: it recovered one false positive while widening the false-negative surface of two rules. ### Engine, not rules: input normalisation Matching now runs against a normalised copy of the listing (NFKC, homoglyph folding for Cyrillic, Greek and Latin small capitals, zero-width and soft-hyphen stripping, spaced-out letter runs closed up). Evasion detection went from 16/66 to 35/66 with zero new false positives and no change to any pattern. The user's text is never rewritten: offsets are mapped back so a match on normalised `cures` inside `c u r e s` highlights all nine original characters. --- ## 2026.07 — updated 15 July 2026 ### Vocabulary pass 2: band-A/B coverage, recall 36.3% → 98.8% The [accuracy benchmark](BENCHMARK.md) exposed that the engine caught only its canonical trigger phrasing. On the committed 200-item violation corpus, bands A + B (blunt and realistic seller language — the copy an enforcement action is actually about) scored **36.3% any-flag recall**. This pass expands the `patterns` arrays of all seven rules against the benchmark's verbatim miss list — no new test strings were invented, and the corpus was not touched. - **Shape, not just vocabulary.** The root cause was narrow literals: `only 3 left` fired but `only 2 remaining` did not; `5 stars` fired but `five-star` did not; `now only £19` fired but `now just £9.99` did not. Patterns now carry number-words (one–twenty), hyphenated forms, adverb variants (only / just / merely) and synonym slots (left | remaining | in stock | available). - **health** — verb + health-noun pairing widened (promotes/aids/eases/maintains/restores + mobility, cartilage, digestion, tissue repair, cholesterol, recovery); authority-implication claims (dermatologist-approved, clinically tested); colds/flu and bloating/IBS conditions. - **reviews** — N-star and word-form star ratings, top-rated / highest-rated, N+ social proof, testimonials, and incentive-within-proximity of a review/rating action. - **subst** — efficacy framings without "proven": studies show, N out of N users, N% reported, backed by research, third-party / lab tested, evidence-based, delivers Nx. - **pricing** — reference-price shapes (was/now with any adverb, RRP/MSRP, save £N, list/regular price, compare at, typically £N elsewhere) and drip pricing (fees added at checkout). - **super** — world's best, the ultimate/finest, most powerful … in the world, unbeatable, market-leading, second to none, and the other absolutes from the miss list. - **green** — the 2024/825 vocabulary: net zero, plastic-free, climate/carbon neutral, planet- friendly, responsibly sourced, sustainable, minimal environmental impact. Bare *green*, *natural*, *carbon* and *planet* are deliberately **not** matched — the clean corpus uses all four innocently (green tea, natural cotton, carbon fibre, Planet Earth). - **urgency** — number-words + stock synonyms, limited-time, while stocks last, offer expires in, hurry / act now, selling fast, N sold in the last N hours, down to the final few. **Two known false positives fixed** by tightening (never widening) the offending patterns: *"the miracle berry plant"* (a botanical proper name, exempted from the `miracle` puffery match) and *"our number one seller … according to our own sales data"* (a superlative that states its own basis — the qualified form CAP guidance contemplates — exempted when a stated basis follows). Result on the frozen corpus: A + B any-flag recall **36.3% → 98.8%** (band A 100%, band B 97.5%), clean-corpus precision **99.0% → 100.0%**. Band C (semantic paraphrase, 0/40) is unchanged and out of reach by design. Engine, severities, categories and law anchors are byte-identical; only `patterns` grew. The two remaining A/B misses are reviews items with no review/rating/feedback word at all ("resounding thumbs up"), which a deterministic matcher cannot reach. ### Citation precision: EmpCo 2024/825 application date The `green` rule's displayed regime now gives the application date of the Empowering Consumers Directive: **"Empowering Consumers Directive (2024/825, applies from 27 Sept 2026)"**. The directive is in force but its national measures do not apply until 27 September 2026, and a citation without that date implies an obligation that has not yet landed. Display string only — no change to any pattern, severity or law-anchor URL, so detection behaviour is identical. --- The rule pack covers **7 rules**: | Rule | Category | Severity | | --- | --- | --- | | `health` | Medical or health claim | High | | `reviews` | Fake or incentivised reviews | High | | `subst` | Unsubstantiated efficacy claim | Medium | | `pricing` | Misleading or drip pricing | Medium | | `green` | Unqualified environmental claim | Medium | | `urgency` | Possible false urgency or scarcity | Medium | | `super` | Unqualified superlative or absolute claim | Low | ### Changed - **`health` — detection vocabulary expanded (2 → 15 patterns).** The rule previously caught only cure/treat/prevent and "clinically proven", missing the entire soft-claim vocabulary that supplement and cosmetic sellers actually use. Now also covers: treatment and recovery verbs (heals, relieves, alleviates, soothes) when they land on a named condition or symptom; physiological-effect verbs (boosts, supports, strengthens, improves) when they land on a body system — the classic EU Regulation (EC) 1924/2006 general-function claims and the US FDA structure/function boundary; the detox and cleanse family; inflammation and pain relief; and biocidal/antimicrobial claims, which are a distinct regulatory trigger under the EU Biocidal Products Regulation 528/2012 and the FDA. - **`reviews` — detection vocabulary expanded (6 → 18 patterns).** The rule previously caught little beyond "verified 5-star". Now also covers: fabricated reviews (fake, paid, bought, seeded, review exchange); **incentivised reviews** — a review request within a short distance of an incentive (discount, % off, free gift, refund, gift card, voucher, giveaway), in both orderings, which is the most common real-world breach and what marketplaces suspend for; and unsubstantiated social proof (rated N stars, loved by thousands, trusted by N+ customers, real testimonials). Negation-guarded, so "we never use fake reviews" is not flagged as a claim. - **`urgency` — severity raised Low → Medium.** False scarcity and countdown pressure are a per-se banned practice under UCPD Annex I, the same legal status as fake reviews. Low understated it. ### Law-anchor precision - `health` now names the instrument: **EU health-claims Regulation (EC) 1924/2006** (was "EU health-claims rules"). - `green` now cites the **Empowering Consumers Directive (EU) 2024/825** (generic environmental claims banned from 27 September 2026) and the **Bill C-59 greenwashing provisions** of Canada's Competition Act specifically, rather than the generic act reference. ### Notes - The rule pack gained `version` and `last_verified` metadata. These are metadata only — the engine skips them and never compiles them as rules. - No change to the matcher, the negation guard, or the dedupe logic.