From 9f806469f37742be65f778059bf364308c9d2811 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Wed, 6 May 2026 15:17:00 +0200 Subject: [PATCH] =?UTF-8?q?fix(ms-ai-architect):=20playground=20v1.13.1=20?= =?UTF-8?q?=E2=80=94=20visuelle=20bugs=20i=20v1.13.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10 visuelle bugs identifisert av maintainer i nettleser etter v1.13.0 shipped. Patch-pakke som adresserer mismatch mellom playground-rendrere og DS-konvensjoner som v1.13.0 ikke fanget opp. - B7: classify "Forpliktelser" indent — lokal .report-meta CSS-reset (DL grid max-content+1fr, h4 uppercase+bold, ul padding-left space-5) for konsistent venstre-justering uavhengig av nestelse. - B8a: requirement-expand handler missing — renderRequirements markup hadde data-action="requirement-expand" på hver expansion__head, men ingen ACTIONS-handler var registrert. R-01..R-09-radene i AI Act-krav var derfor ikke klikkbare. Fix: register ACTIONS['requirement-expand']. - B8b: expansion title-main + title-sub kjørte sammen — DS' spans var inline. Lokal display:block så de stables vertikalt. - B10: kanban-card tegnknekking — DS' word-break:break-all knekker midt i ord. Lokal override med break-word. - B11: DPIA matrix-bobler ikke responderer — v1.13.0 click-handler matchet kun mot første-kolonne i Trusler-tabellen. DPIA-fixturer har full-tekst label i matrix_cells men T-001-id i threats-tabellen, så ingen match. Utvid til (Pass 1) exact first-cell + (Pass 2) substring- match mot enhver celle med 40-tegn-prefiks-toleranse. - B12, B13, B15: defensive layout for top-risks/suppressed-panel/ phase-detail/aiact-timeline — eksplisitt display:block; clear:both; width:100% mot grid-leak fra small-multiples/kanban-board/mat-ladder. - B14: Migrate "skal vel være tabell" — phases-summary-tabell over phase-detail-seksjonene (Fase, Varighet, Milepæler-count, Suksesskriterier- count, Status). Samme tabell speilet i renderPoc for konsistens. Verifisering: - 23/23 smoke-test PASS (B7-B15 + 5 v1.13.0-regresjoner) - 271/271 playground E2E PASS - 219 plugin-validering PASS - 42 KB-update PASS Versjon: v1.13.0 -> v1.13.1 (plugin.json, README badge, README version-history, CHANGELOG, ROADMAP, TODO, plugin CLAUDE.md playground-header, root README plugin-list, root CLAUDE.md plugin-list). Berører kun lokal CSS i @@ -4104,6 +4145,23 @@ '' + escapeHtml(cur.name) + '' + ''; } + // v1.13.1 fix (B14): brukeren etterspurte tabell-visning. Legg til en + // phases-summary-tabell over phase-detail-seksjonene som gir oversikt + // (Fase, Varighet, Milepæler-count, Suksess-count, Status). + const phasesSummaryRows = phases.map(function (p, i) { + const state = stepStateFor(p, i); + const stateLabel = state === 'completed' ? 'Ferdig' : state === 'current' ? 'Pågår' : 'Planlagt'; + return '' + + '' + escapeHtml(p.name) + '' + + '' + escapeHtml(String(p.duration_weeks || '—')) + ' uker' + + '' + ((p.milestones || []).length) + '' + + '' + ((p.success_criteria || []).length) + '' + + '' + escapeHtml(stateLabel) + '' + + ''; + }).join(''); + const phasesSummaryHtml = phasesSummaryRows + ? '' + phasesSummaryRows + '
FaseVarighetMilepælerSuksesskriterierStatus
' + : ''; const detailsHtml = phases.map(function (p) { const ms = (p.milestones || []).map(function (m) { return '
  • ' + escapeHtml(m) + '
  • '; }).join(''); const sc = (p.success_criteria || []).map(function (s) { return '
  • ' + escapeHtml(s) + '
  • '; }).join(''); @@ -4119,7 +4177,7 @@ const risksHtml = risksRows ? '' + risksRows + '
    RisikoSannsynlighetKonsekvensTiltak
    ' : ''; - const body = ribbonHtml + ladderHtml + detailsHtml + risksHtml; + const body = ribbonHtml + ladderHtml + phasesSummaryHtml + detailsHtml + risksHtml; slot.innerHTML = renderPageShell({ eyebrow: 'MIGRASJON', title: data.title || 'Migrasjonsplan', @@ -4281,6 +4339,23 @@ ''; }).join(''); const ladderHtml = '
    ' + stepsHtml + '
    '; + // v1.13.1 fix (B15): phases-summary-tabell over phase-detail-seksjonene + // gir struktur og forhindrer at faseinfo flyter horisontalt mot risiko- + // tabellen i renderPoc. Samme mønster som renderMigrate. + const phasesSummaryRows = phases.map(function (p, i) { + const state = stepStateFor(p, i); + const stateLabel = state === 'completed' ? 'Ferdig' : state === 'current' ? 'Pågår' : 'Planlagt'; + return '' + + '' + escapeHtml(p.name) + '' + + '' + escapeHtml(String(p.duration_weeks || '—')) + ' uker' + + '' + ((p.milestones || []).length) + '' + + '' + ((p.success_criteria || []).length) + '' + + '' + escapeHtml(stateLabel) + '' + + ''; + }).join(''); + const phasesSummaryHtml = phasesSummaryRows + ? '' + phasesSummaryRows + '
    FaseVarighetMilepælerSuksesskriterierStatus
    ' + : ''; // B5 traffic-light per success-kriterie. R15: uten eksplisitt status, // bruk fasens state — done=go, active=warning, future=neutral. const detailsHtml = phases.map(function (p, i) { @@ -4307,7 +4382,7 @@ const risksHtml = risksRows ? '' + risksRows + '
    RisikoSannsynlighetKonsekvensTiltak
    ' : ''; - const body = ladderHtml + detailsHtml + risksHtml; + const body = ladderHtml + phasesSummaryHtml + detailsHtml + risksHtml; // B1 verdict-pille: data.pocVerdict styrer (go/go-with-conditions/block). // R15: hvis ikke satt, fall tilbake til risk-baserte heuristikk. let verdict = data.verdict || data.pocVerdict; @@ -5283,28 +5358,54 @@ // v1.13.0 fix (B3): matrix-bobler klikkbare. Klikk scroller til tilsvarende // rad i Trusler-tabellen og fremhever den kort. Bruker data-threat-id som - // anker (matchet mot første kolonne i tabellen). Speilet fra llm-security - // v7.6.1 commit f9b555a. + // anker. Speilet fra llm-security v7.6.1 commit f9b555a. + // + // v1.13.1 fix (B11): DPIA-fixturer har full-tekst label i matrix_cells men + // T-001..T-005-id i threats-tabellen. Matchet kun mot første-kolonne ga + // klikk uten effekt. Utvid match-strategi: prøv first-cell exact, så + // any-cell substring-match (fuzzy). Også legg til normalisering for å + // håndtere truncation (escapeHtml + slice). document.addEventListener('click', function (ev) { const bubble = ev.target.closest('.matrix__bubble[data-threat-id]'); if (!bubble) return; const threatId = bubble.getAttribute('data-threat-id'); if (!threatId) return; + const norm = function (s) { return String(s || '').trim().toLowerCase(); }; + const target = norm(threatId); + const targetHead = target.slice(0, 40); const tables = document.querySelectorAll('table.report-table'); + // Pass 1: exact match på første-kolonne (T-001-mønster). for (let t = 0; t < tables.length; t++) { const rows = tables[t].querySelectorAll('tbody tr'); for (let r = 0; r < rows.length; r++) { const firstCell = rows[r].querySelector('td'); - if (firstCell && firstCell.textContent.trim() === threatId) { - rows[r].scrollIntoView({ behavior: 'smooth', block: 'center' }); - const orig = rows[r].style.background; - rows[r].style.background = 'var(--color-primary-100, var(--color-bg-soft))'; - rows[r].style.transition = 'background var(--duration-base) var(--ease-default)'; - setTimeout(function () { rows[r].style.background = orig; }, 1600); + if (firstCell && norm(firstCell.textContent) === target) { + highlightRow(rows[r]); return; } } } + // Pass 2: substring-match mot enhver celle i raden (label-baserte data-id). + for (let t = 0; t < tables.length; t++) { + const rows = tables[t].querySelectorAll('tbody tr'); + for (let r = 0; r < rows.length; r++) { + const cells = rows[r].querySelectorAll('td'); + for (let c = 0; c < cells.length; c++) { + const cellText = norm(cells[c].textContent); + if (cellText && (cellText.indexOf(targetHead) !== -1 || target.indexOf(cellText.slice(0, 40)) !== -1)) { + highlightRow(rows[r]); + return; + } + } + } + } + function highlightRow(row) { + row.scrollIntoView({ behavior: 'smooth', block: 'center' }); + const orig = row.style.background; + row.style.background = 'var(--color-primary-100, var(--color-bg-soft))'; + row.style.transition = 'background var(--duration-base) var(--ease-default)'; + setTimeout(function () { row.style.background = orig; }, 1600); + } }); ACTIONS['onboarding-toggle-group'] = function (ev, el) { @@ -5314,6 +5415,17 @@ exp.setAttribute('aria-expanded', open ? 'false' : 'true'); }; + // v1.13.1 fix (B8a): renderRequirements bruker data-action="requirement-expand" + // på hver expansion__head-knapp, men handleren var aldri registrert. Klikk + // gjorde derfor ingenting på R-01..R-09-radene i AI Act-krav-rapporten. + // Samme toggle-mønster som onboarding/catalog. + ACTIONS['requirement-expand'] = function (ev, el) { + const exp = el.closest('.expansion'); + if (!exp) return; + const open = exp.getAttribute('aria-expanded') === 'true'; + exp.setAttribute('aria-expanded', open ? 'false' : 'true'); + }; + ACTIONS['onboarding-goto-group'] = function (ev, el) { const groupId = el.dataset.group; const root = getSurfaceEl('onboarding');