Cannabis Freedom Index

Changelog 8130c5f

#194 require verified THC limits for driving classes

2 country profiles edited5 files of code, design or docs +51 −9 lines

Countries and states 2 files

Kenya countries/ke.yaml

context › driving › status

limitunknown

context › driving › text

The Traffic Act makes it an offence to drive, attempt to drive or be in charge of a vehicl … disqualification for twelve months. The section itself gives no figure for cannabis, and none was found inno numerical THC cutoff has been verified. The reviewed 2026 Drink-Driving Rules prescribe blood-alcohol concentrations, not THC; the sources read for this profilecannabis-specific conviction trigger remains unverified.[@ta44,drink2026]

context › driving › sources

ta44, drink2026

sources

Kenya Law — Traffic (Drink-Driving) Rules, Legal Notice 12 of 2026 7 unchanged

New Zealand countries/nz.yaml

context › driving › text

Police can stop any driver and screen saliva at the roadside for four drugs, THC among the … e spot. A fine follows only if the laboratory confirms the drug at or above its threshold (5 ng/mL of THC in oral fluid): 200 dollars and 50 demerit points for one drug, 400 dollars and 75 points for two or mor … st and may apply afterwards for a medical defence if they took the medicine as prescribed.

context › driving › sources

lab2025, pdd1, pdd2, pdd3, pdd4

sources

New Zealand — Land Transport (Concentration Level of Listed Qualifying Drugs) Notice 2025 17 unchanged

Code, design and documents 5 files

docs/DATA-MAINTENANCE.md +4 −0
@@ -239,4 +239,8 @@ context:
   a binding ruling requires more than detection. Give the limit and its unit, the penalty and
   licence consequences, and any separate rule for medical patients, novice or professional drivers.
+- Use `driving.status: unknown` when a reviewed law mentions drug-driving but the cannabis-specific
+  conviction trigger remains unverified. Keep the sourced explanation; the map leaves it hatched.
+  A `limit` classification needs a numerical THC concentration, unit and supporting primary
+  source, not merely the phrase "prescribed limits" or an alcohol threshold.
 - **`visitors.status`** is whether someone who does not live in the country can get cannabis
   legally: `open` (same terms as residents), `residents` (legal supply is for residents only) or

docs/research/issue-corrections-186-204-2026-10-27.md +13 −0
@@ -50,2 +50,15 @@ The classification is not a claim that the entire plant has been rescheduled as
 narcotic. Existing explanation of prescription access and practical shop closures
 remains. Added the direct official notice to visitor sources.
+
+## #194 — Verified driving trigger and numerical limits
+
+Read Kenya's 2026 Drink-Driving Rules in the normal browser at Kenya Law, regulation
+3: the prescribed concentrations are expressly blood-alcohol concentrations. Section
+44's general prescribed-limits phrase is insufficient to label a fixed THC offence.
+Added an explicit unknown reviewed trigger, hatched on the map, retaining the cited
+legal text and penalties without inventing an impairment or detectable-THC test.
+No claim that drug driving is lawful. The regression audits every fixed-limit
+profile for a numerical concentration and source. That audit found New Zealand's
+existing fixed-threshold description lacked the number: read the official 2025/247
+notice and added 5 ng/mL THC in oral fluid, an evidential laboratory threshold,
+not the separate roadside device threshold. Its source/commencement is recorded.

scripts/profile-claims.test.mjs +11 −0
@@ -376,2 +376,13 @@ test('Thailand medical-only flower status agrees with its explanation (#193)', (
   assert.match(th.context.planting.text, /seed|plant/i);
 });
+
+// Issue #194
+test('fixed THC classes require numerical evidence; Kenya remains unverified (#194)', () => {
+  assert.equal(country('ke').context.driving.status, 'unknown');
+  for (const name of fs.readdirSync(path.join(root,'countries')).filter(n=>n.endsWith('.yaml'))) {
+    const p = country(name.slice(0,-5)), d = p.context?.driving;
+    if (d?.status !== 'limit') continue;
+    assert.match(d.text, /\d+(?:\.\d+)?\s*(?:nanograms?|microgram(?:me)?s?|ng|µg|mg)/i, name);
+    assert.ok(d.sources.some(k => p.sources[k]?.url), name+' needs a source for its numerical rule');
+  }
+});

src/components/HomePage.astro +2 −2
@@ -146,5 +146,5 @@ const LAW_SECTIONS = {
 const MAP_SECTIONS = { ...LAW_SECTIONS, ...STATUS_SECTIONS };
 const STATUS_SCALES = Object.fromEntries(Object.entries(MAP_SECTIONS).map(([key, section]) => [key, { name: section.name,
-  scale: Object.fromEntries(Object.entries(section.statuses).map(([k, v]) => [k, { label: v.label, help: v.help, color: `var(--t${section.tiers[k]})` }])) }]));
+  scale: Object.fromEntries(Object.entries(section.statuses).map(([k, v]) => [k, { label: v.label, help: v.help, color: section.tiers[k] == null ? "url(#hatch)" : `var(--t${section.tiers[k]})` }])) }]));
 // the map's views in groups, as [metric, label]: the tabs and rows of the view picker
 const datasetViews = (group) => MAPPED.filter((ds) => ds.map.group === group).map((ds) => [`data:${ds.id}`, ds.map.label]);
@@ -519,5 +519,5 @@ const columnGroups = [["Shown by default", BASE_COLUMNS], ...["Score segments",
   <script type="application/json" id="cfi-freedom-years" set:html={JSON.stringify(FREEDOM_YEARS)} />
   <script type="application/json" id="cfi-price-scale" set:html={JSON.stringify(PRICE_SCALE)} />
-  <script type="application/json" id="cfi-planting" set:html={JSON.stringify({ fields: PLANTING_FIELDS, scales: PLANTING_SCALES, sections: STATUS_SCALES, subs: Object.fromEntries(Object.entries(MAP_SECTIONS).map(([key, section]) => [key, section.complete ? section.sub : `${section.sub} Hatched countries have not been researched yet. Not part of the score.`])) })} />
+  <script type="application/json" id="cfi-planting" set:html={JSON.stringify({ fields: PLANTING_FIELDS, scales: PLANTING_SCALES, sections: STATUS_SCALES, subs: Object.fromEntries(Object.entries(MAP_SECTIONS).map(([key, section]) => [key, section.complete ? section.sub : `${section.sub} ${key === "driving" ? "Hatched countries have an unverified trigger or have not been researched yet." : "Hatched countries have not been researched yet."} Not part of the score.`])) })} />
   <script type="application/json" id="cfi-segments" set:html={JSON.stringify(SEGMENTS.map((s) => ({ name: s.name, desc: s.desc, levels: s.levels })))} />
 

src/lib/segment-ids.js +3 −2
@@ -32,4 +32,5 @@ export const CLUBS_STATUS = {
 // Driving after use: what the law needs to convict a driver. Not part of the score.
 export const DRIVING_STATUS = {
+  unknown: { label: "Drug-driving trigger unverified", tone: "grey", help: "Drug-driving rules were reviewed, but no cannabis-specific offence trigger or THC cutoff was established" },
   impairment: { label: "Impairment must be shown", tone: "legal", help: "The reviewed driving offence requires evidence of drug influence or impairment; additional offences may apply" },
   capacity: { label: "Capable of affecting driving", tone: "decrim", help: "A conviction needs the drug in a biological sample and proof it was capable of affecting driving. A driving mistake is outside that proof" },
@@ -50,6 +51,6 @@ export const STATUS_SECTIONS = {
     sub: "Green means cannabis clubs are regulated or tolerated, orange that they work underground, red that none are known.",
     note: "The footing cannabis clubs stand on. Licensed shops and pharmacies are not counted as clubs." },
-  driving: { name: "Driving", chip: "Driving", statuses: DRIVING_STATUS, tiers: { impairment: 5, capacity: 4, limit: 3, consumption: 2, zero: 0 },
-    sub: "Green marks a drug-influence or impairment offence, light green a rule that needs proof the drug could affect driving, yellow a fixed THC limit, orange a prohibition after consumption, and red a detectable-THC offence. Read each profile for additional rules.",
+  driving: { name: "Driving", chip: "Driving", statuses: DRIVING_STATUS, tiers: { impairment: 5, capacity: 4, limit: 3, consumption: 2, zero: 0, unknown: null },
+    sub: "Green marks a drug-influence or impairment offence, light green a rule that needs proof the drug could affect driving, yellow a fixed THC limit, orange a prohibition after consumption, and red a detectable-THC offence. Hatched means the cannabis-specific trigger is unverified. Read each profile for additional rules.",
     note: "What the law needs to convict a driver who has used cannabis." },
   visitors: { name: "Visitors and foreigners", chip: "Visitors", statuses: VISITORS_STATUS, tiers: { open: 5, residents: 3, none: 0 },

    ↑↓ to move, ↵ to open.