// tests/kb-update/test-governance-refs-reg-lint.test.mjs // TDD for RX-REG-KB (kryssmodell-review 2026-07-09, replan §RX-REG-KB): the // governance reference corpus carried EU AI Act errors that ground-truth // verification (EUR-Lex CELEX:32024R1689, AI Act Explorer, regjeringen.no) // confirmed as factually wrong. This lint is the *preventive mechanism* // (gap-disiplin): once the surgical fixes land, these literals must never // re-enter the corpus. // // Ground truth locked this session: // - Art. 5(1) letters: (c) social scoring is NOT public-authority-limited; // (d) crime-risk prediction by profiling; (e) untargeted facial-image // scraping; (h) real-time RBI for law enforcement. The old table // scrambled (c)/(d)/(e)/(h) and omitted scraping. (EUR-Lex art. 5(1).) // - Art. 6(2): Annex III = high-risk MAIN RULE; Art. 6(3): narrow 4-condition // exception; profiling ⇒ ALWAYS high-risk. The old decision tree inverted // this (profiling as the sole trigger). (EUR-Lex art. 6(2)-(3).) // - Art. 99 fines: (3) €35M/7 %; (4) incl. Art. 50 transparency (4)(g) €15M/3 %; // (5) incorrect info €7,5M/1 %; (6) SMEs = «whichever is LOWER», NO separate // reduced amounts. The old table put transparency at 7,5M/1,5 %, false-info // at 1,5 %, and fabricated an SMB column. (EUR-Lex art. 99(3)-(6).) // - Art. 49 registration timing = before placing on market / putting into // service — NOT a fixed «fra august 2026». High-risk applicability deferred // to 2027-12-02 (Annex III) / 2028-08-02 (Annex I) via Digital Omnibus. // - Bokføringsloven § 13: 5 år (not «7 år»). // - Nkom is the DESIGNATED coordinating market-surveillance authority // (regjeringen besluttet) — «under etablering» is stale. // - Digital Omnibus dropped any acceleration trigger → «fremskynde» must go. import { test } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; const pluginRoot = new URL('../../', import.meta.url); const REF = 'skills/ms-ai-governance/references/responsible-ai/'; const read = (rel) => readFileSync(new URL(REF + rel, pluginRoot), 'utf8'); // Files in scope for this session's RX-REG-KB fixes. const GOVERNANCE_FILES = [ 'ai-act-classification-methodology.md', 'ai-act-compliance-guide.md', 'ai-act-conformity-assessment.md', 'ai-act-provider-obligations.md', 'ai-act-fria-template.md', 'ai-act-deployer-obligations.md', ]; // --- 0. Cross-file guards (apply to every governance ref) --- test('no refuted Omnibus-acceleration claim survives anywhere', () => { for (const f of GOVERNANCE_FILES) { assert.ok(!/fremskynde/i.test(read(f)), `${f}: «fremskynde» — the final Omnibus dropped the acceleration trigger`); } }); test('no stale «under etablering» authority phrasing survives (Nkom is designated)', () => { for (const f of GOVERNANCE_FILES) { assert.ok(!/under etablering/i.test(read(f)), `${f}: «under etablering» — Nkom is the designated coordinating authority`); } }); // --- 1. Art. 5(1) prohibited-practices table (classification-methodology) --- test('classification-methodology: Art. 5(1) letters are correctly assigned', () => { const md = read('ai-act-classification-methodology.md'); // Forbidden: the old scrambled letter↔content pairings. assert.ok(!md.includes('Sosial scoring av enkeltpersoner av offentlige myndigheter'), '(c) social scoring is not limited to public authorities'); assert.ok(!md.includes('Sanntids biometrisk fjernidentifikasjon i offentlig rom (Art. 5(1)(d))'), 'real-time RBI is (h), not (d)'); assert.ok(!md.includes('Retrospektiv biometrisk identifikasjon uten lovhjemmel'), '(e) is untargeted facial-image scraping, not retrospective ID'); assert.ok(!/basert på profiling \(Art\. 5\(1\)\(h\)\)/.test(md), 'crime prediction by profiling is (d), not (h)'); // Required: the correct pairings + the missing scraping row. assert.ok(/skraping av ansiktsbilder/i.test(md), '(e) scraping row must exist'); assert.ok(/profilering \(Art\. 5\(1\)\(d\)\)/.test(md), '(d) crime-risk prediction by profiling'); assert.ok(/rettshåndhevelse \(Art\. 5\(1\)\(h\)\)/.test(md), '(h) real-time RBI for law enforcement'); }); // --- 2. Art. 6(2)/(3) high-risk classification (compliance-guide decision tree) --- test('compliance-guide: Annex III is high-risk by default (Art. 6(2)/(3))', () => { const md = read('ai-act-compliance-guide.md'); assert.ok(md.includes('Art. 6(2)'), 'Annex III = high-risk main rule (Art. 6(2))'); assert.ok(md.includes('Art. 6(3)'), 'narrow exception cited (Art. 6(3))'); }); // --- 3. Art. 99 administrative fines (compliance-guide) --- test('compliance-guide: Art. 99 fine figures are correct + SMB rule cited', () => { const md = read('ai-act-compliance-guide.md'); // Forbidden: wrong transparency %, wrong false-info %, fabricated SMB column. assert.ok(!/1,5\s?%/.test(md), 'no 1,5 % anywhere (transparency=3 %, false-info=1 %)'); assert.ok(!/0,6\s?%/.test(md), 'no fabricated SMB 0,6 %'); assert.ok(!/0,3\s?%/.test(md), 'no fabricated SMB 0,3 %'); // Required: Art. 99(6) SMB rule = «whichever is lower». assert.ok(md.includes('Art. 99(6)'), 'SMB rule Art. 99(6) must be cited'); assert.ok(/laveste/i.test(md), 'SMB = «whichever thereof is lower»'); }); // --- 4. AI Act applicability dates (compliance-guide): no stale «august 2026» --- test('compliance-guide: no stale «august 2026» high-risk applicability strings', () => { const md = read('ai-act-compliance-guide.md'); assert.ok(!/2\.?\s*august 2026:\*\* Providers må registrere/.test(md), 'registration is Art. 49 timing, not a fixed aug-2026 date'); assert.ok(!/august 2027:\*\* Full compliance/.test(md), 'high-risk deferred to 2027-12-02'); assert.ok(!/fra aug\.? 2026/i.test(md), 'no «fra aug 2026» registration string'); assert.ok(!/\(påkrevd fra august 2026\)/.test(md), 'no «påkrevd fra august 2026»'); assert.ok(!/fra før august 2026/.test(md), 'transition cutoff = applicability date, not aug 2026'); assert.ok(!/Før august 2026: mindre press/.test(md), 'stale advisory date'); // Required: the corrected deferred date. assert.ok(md.includes('2. desember 2027'), 'Annex III high-risk applies 2027-12-02'); }); // --- 5. Bokføringsloven retention (compliance-guide): 5 år, not 7 år --- test('compliance-guide: log retention is 5 år (bokføringsloven § 13), not 7 år', () => { const md = read('ai-act-compliance-guide.md'); assert.ok(!/7 år/.test(md), 'bokføringsloven § 13 = 5 år primær, not 7 år'); assert.ok(/5 år/.test(md), 'corrected retention present'); }); // --- 6. Nkom named in the three files that carried «under etablering» --- for (const f of ['ai-act-provider-obligations.md', 'ai-act-fria-template.md', 'ai-act-deployer-obligations.md']) { test(`${f}: names Nkom as designated authority`, () => { assert.ok(read(f).includes('Nkom'), 'Nkom (koordinerende markedstilsynsmyndighet) must be named'); }); } // --- 7. M13 article-number citations (EUR-Lex CELEX:32024R1689 / AI Act Explorer, verified 2026-07-15) --- // Ground truth this session (RX-REG-KB Økt 2, cluster «artikkelnr.»): // - Registration duty = Art. 49 ("Registration"). Art. 71 is the EU DATABASE entity // ("EU Database for High-Risk AI Systems Listed in Annex III"). Lines describing the ACT // of registering must cite Art. 49, not Art. 71. // - Serious-incident reporting = Art. 73 ("Reporting of Serious Incidents"). Art. 72 is // post-market monitoring — correct where it means monitoring, wrong for incidents. // - Substantial modification: definition = Art. 3(23); new-conformity trigger = Art. 43(4). // Art. 83 is "Formal non-compliance" — never a substantial-modification citation. // - Annex III 5(c) = risk assessment & pricing in life and health insurance (5(d) = emergency dispatch). // - Six-month log retention = Art. 19(1) ("Automatically generated logs"); Art. 12 is the // record-keeping capability, not the retention duration. test('conformity-assessment: registration act = Art. 49; substantial-mod def = Art. 3(23)', () => { const md = read('ai-act-conformity-assessment.md'); assert.ok(!/\(Art\. 71\)/.test(md), 'registration act cites Art. 49, not the Art. 71 database entity'); assert.ok(!/substantial modification, Art\. 83\)/.test(md), 'substantial-mod definition = Art. 3(23), not Art. 83'); assert.ok(/\(Art\. 49\)/.test(md), 'Art. 49 registration citation present'); assert.ok(/Art\. 3\(23\)/.test(md), 'Art. 3(23) substantial-mod definition present'); }); test('microsoft-tools-mapping: serious incidents = Art. 73; registration = Art. 49', () => { const md = read('ai-act-microsoft-tools-mapping.md'); assert.ok(!/\*\*Art\. 72\*\* Alvorlige hendelser/.test(md), 'serious incidents = Art. 73, not Art. 72'); assert.ok(!/alvorlig-hendelse-rapportering \(Art\. 72\)/.test(md), 'serious-incident reporting = Art. 73'); assert.ok(!/\(Art\. 71\)/.test(md), 'registration act = Art. 49, not Art. 71'); assert.ok(/Art\. 73/.test(md), 'Art. 73 serious-incident citation present'); }); test('transparency-notices: substantial-mod re-conformity = Art. 43(4)', () => { const md = read('ai-act-transparency-notices.md'); assert.ok(!/"vesentlig" \(Art\. 83\)/.test(md), 're-conformity on substantial mod = Art. 43(4), not Art. 83'); assert.ok(/Art\. 43\(4\)/.test(md), 'Art. 43(4) present'); }); test('fria-template + deployer-obligations: insurance = Annex III 5(c), not 5(d)', () => { for (const f of ['ai-act-fria-template.md', 'ai-act-deployer-obligations.md']) { const md = read(f); assert.ok(!/Annex III pkt\. 5\(d\)/.test(md), `${f}: life/health insurance = Annex III 5(c), not 5(d)`); assert.ok(/Annex III pkt\. 5\(c\)/.test(md), `${f}: Annex III 5(c) present`); } }); test('provider-obligations: six-month log retention = Art. 19(1), not Art. 12', () => { const md = read('ai-act-provider-obligations.md'); assert.ok(!/Art\. 12\(2\) krever minst 6 måneder/.test(md), 'retention duration = Art. 19(1), not Art. 12(2)'); assert.ok(!/6-måneder minimum \(Art\. 12\)/.test(md), '6-month minimum retention = Art. 19(1), not Art. 12'); assert.ok(/Art\. 19\(1\)/.test(md), 'Art. 19(1) retention citation present'); }); // --- 8. M13 applicability-date nuance (Digital Omnibus deferral, verified 2026-07-15) --- // Ground truth (RX-REG-KB Økt 3, cluster «M13-frister»): the high-risk obligation // package — conformity assessment (Art. 43), CE marking (Art. 48), EU-database // registration (Art. 49) and record-keeping (Art. 12) — is deferred for stand-alone // Annex III systems from 2026-08-02 to 2027-12-02 via the Digital Omnibus (adopted, // pending OJ). Canonical: scripts/kb-update/data/ai-act-deadlines.json. Each file // below already carries the corrected 2027-12-02 date elsewhere; the registration/ // CE/record-keeping lines must not contradict it with a hard «2. august 2026» deadline. const readMon = (rel) => readFileSync(new URL('skills/ms-ai-governance/references/monitoring-observability/' + rel, pluginRoot), 'utf8'); test('conformity-assessment: Art. 49 registration is not a hard «2. august 2026» deadline', () => { const md = read('ai-act-conformity-assessment.md'); assert.ok(!/obligatorisk fra 2\.?\s*august 2026/.test(md), 'registration = pre-market (Art. 49); high-risk applicability deferred to 2027-12-02'); assert.ok(/2\. desember 2027/.test(md), 'corrected deferred date present'); }); test('microsoft-tools-mapping: conformity/CE deadline is 2027-12-02, not «2. august 2026»', () => { const md = read('ai-act-microsoft-tools-mapping.md'); assert.ok(!/\(FØR 2\.?\s*august 2026\)/.test(md), 'phase header must not present aug-2026 as the legal deadline'); assert.ok(!/fullført før 2\.?\s*august 2026/.test(md), 'CE/registration goal must not cite aug-2026 as deadline'); assert.ok(!/2\.?\s*august 2026 er den kritiske datoen/.test(md), 'critical date for conformity/CE = 2. desember 2027, not 2. august 2026'); assert.ok(/2\.?\s*des(?:ember)? 2027/.test(md), 'corrected deferred date present'); }); test('data-residency: Art. 12 record-keeping baseline reflects the deferred high-risk date', () => { const md = readMon('data-residency-audit-monitoring.md'); assert.ok(!/enforcement starter 2026-08-02/.test(md), 'Art. 12 is a high-risk obligation deferred to 2027-12-02, not enforced from 2026-08-02'); assert.ok(/2027/.test(md), 'deferred date reference present'); });