feat(ms-ai-architect): RX-REG — én maskinlesbar AI Act-frist-kilde + synk-test (B2-B5, R3-5, M10) [skip-docs]

Rotårsak-mekanisme: scripts/kb-update/data/ai-act-deadlines.json er nå eneste
kilde for AI Act-frister; CLAUDE.md-tabellen, assessor-malen og begge hooks
synk-testes mot den (tests/kb-update/test-ai-act-deadlines-sync.test.mjs, 9
tester, TDD rød→grønn). Suite 815/815.

- B2: «Kommisjonen kan fremskynde»/«ytre grense» fjernet (trigger droppet i
  endelig Omnibus-tekst)
- B3: status oppdatert i alle 3 lag — formelt vedtatt (EP 2026-06-16, Rådet
  2026-06-29), trer i kraft ved OJ-publisering (ikke publisert per 2026-07-15,
  verifisert mot EUR-Lex 32024R1689)
- B4: Art. 50-raden «Gjeldende» → «Fra 2026-08-02»
- B5: stop-hooken feilmerket 2026-08-02 som «GPAI-frist» — begge hooks leser
  nå kilden, 0 hardkodede frist-literals
- R3-5: 2026-12-02-raden (Art. 50(2)) inn i assessor-malen
- M10: Nkom navngitt som koordinerende markedstilsynsmyndighet + nasjonalt
  kontaktpunkt (kilde: nkom.no/ki/regulering/hvem-handhever)
- pending_oj-markører i kilden for RX-REG² (nudifiserings-forbud, Art. 111)
- .gitignore: whitelist for den kuraterte frist-kilden
This commit is contained in:
Kjell Tore Guttormsen 2026-07-15 06:13:36 +02:00
commit a8ae1fd276
8 changed files with 195 additions and 27 deletions

View file

@ -20,6 +20,7 @@ import {
FREE_CONTEXT_FILE,
buildOrgSummary,
} from '../../scripts/kb-update/lib/user-data.mjs';
import { loadAiActDeadlines } from '../../scripts/kb-update/lib/ai-act-deadlines.mjs';
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || join(process.cwd());
const cwd = process.cwd();
@ -93,20 +94,12 @@ if (shouldRunDetection(scheduleConfig, lastPollDaysAgo).run) {
}
}
// --- 3. Check EU AI Act deadlines ---
const AI_ACT_DEADLINES = [
// NB: Digital Omnibus (prov. enighet 2026-05-07) utsatte høyrisiko; datoer foreløpige til OJ-publisering.
{ date: new Date('2025-02-02'), label: 'Forbudte AI-praksiser (Art. 5)' },
{ date: new Date('2025-08-02'), label: 'GPAI-krav + governance/sanksjoner (Art. 99)' },
{ date: new Date('2026-08-02'), label: 'Transparens Art. 50 (syntetisk innhold)' },
{ date: new Date('2026-12-02'), label: 'Art. 50(2) merking — frist for eksisterende generative systemer (Omnibus)' },
{ date: new Date('2027-12-02'), label: 'Annex III høyrisiko (provisorisk, Omnibus — utsatt fra 2026-08-02)' },
{ date: new Date('2028-08-02'), label: 'Annex I høyrisiko innebygd (provisorisk, Omnibus)' },
];
// --- 3. Check EU AI Act deadlines (single source: scripts/kb-update/data/ai-act-deadlines.json) ---
const aiActSource = loadAiActDeadlines();
let nearestDeadline = null;
for (const dl of AI_ACT_DEADLINES) {
const daysLeft = Math.ceil((dl.date.getTime() - now) / DAY_MS);
for (const dl of aiActSource ? aiActSource.deadlines : []) {
const daysLeft = Math.ceil((new Date(dl.date).getTime() - now) / DAY_MS);
if (daysLeft > 0 && daysLeft <= 180) {
if (!nearestDeadline || daysLeft < nearestDeadline.daysLeft) {
nearestDeadline = { ...dl, daysLeft };

View file

@ -5,6 +5,7 @@
import { readdirSync, statSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import { loadAiActDeadlines } from '../../scripts/kb-update/lib/ai-act-deadlines.mjs';
const cwd = process.cwd();
const workDir = join(cwd, '.work');
@ -60,12 +61,18 @@ const suggestions = [
'/architect:summary — lag beslutningsnotat',
];
// Add AI Act suggestion if deadline is within 180 days
// Add AI Act suggestion if the nearest deadline (from the shared source) is within 180 days
const DAY_MS = 24 * 60 * 60 * 1000;
const gpaiDeadline = new Date('2026-08-02');
const daysToGpai = Math.ceil((gpaiDeadline.getTime() - now) / DAY_MS);
if (daysToGpai > 0 && daysToGpai <= 180) {
suggestions.push(`/architect:classify — EU AI Act-klassifisering (${daysToGpai}d til GPAI-frist)`);
const aiActSource = loadAiActDeadlines();
let nearestDeadline = null;
for (const dl of aiActSource ? aiActSource.deadlines : []) {
const daysLeft = Math.ceil((new Date(dl.date).getTime() - now) / DAY_MS);
if (daysLeft > 0 && daysLeft <= 180 && (!nearestDeadline || daysLeft < nearestDeadline.daysLeft)) {
nearestDeadline = { ...dl, daysLeft };
}
}
if (nearestDeadline) {
suggestions.push(`/architect:classify — EU AI Act-klassifisering (${nearestDeadline.daysLeft}d til ${nearestDeadline.label})`);
}
const sessionList = recentSessions.join(', ');